Make stem export export from right before any processors.
[ardour.git] / libs / ardour / ardour / export_channel.h
1 /*
2     Copyright (C) 2008 Paul Davis
3     Author: Sakari Bergen
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21 #ifndef __ardour_export_channel_h__
22 #define __ardour_export_channel_h__
23
24 #include <set>
25
26 #include <boost/signals2.hpp>
27 #include <boost/shared_ptr.hpp>
28 #include <boost/scoped_array.hpp>
29 #include <boost/operators.hpp>
30
31 #include "pbd/signals.h"
32
33 #include "ardour/buffer_set.h"
34
35 namespace ARDOUR {
36
37 class Session;
38 class AudioTrack;
39 class AudioPort;
40 class AudioRegion;
41 class CapturingProcessor;
42
43 /// Export channel base class interface for different source types
44 class ExportChannel : public boost::less_than_comparable<ExportChannel>
45 {
46   public:
47
48         virtual ~ExportChannel () {}
49
50         virtual void set_max_buffer_size(framecnt_t frames) { }
51
52         virtual void read (Sample const *& data, framecnt_t frames) const = 0;
53         virtual bool empty () const = 0;
54
55         /// Adds state to node passed
56         virtual void get_state (XMLNode * node) const = 0;
57
58         /// Sets state from node passed
59         virtual void set_state (XMLNode * node, Session & session) = 0;
60
61         // Operator< must be defined for usage in e.g. std::map or std::set to disallow duplicates when necessary
62         virtual bool operator< (ExportChannel const & other) const = 0;
63 };
64
65 /// Safe pointer for storing ExportChannels in ordered STL containers
66 class ExportChannelPtr : public boost::shared_ptr<ExportChannel>
67                        , public boost::less_than_comparable<ExportChannel>
68 {
69   public:
70         ExportChannelPtr () {}
71         template<typename Y> explicit ExportChannelPtr (Y * ptr) : boost::shared_ptr<ExportChannel> (ptr) {}
72
73         bool operator< (ExportChannelPtr const & other) const { return **this < *other; }
74 };
75
76 /// Basic export channel that reads from AudioPorts
77 class PortExportChannel : public ExportChannel
78 {
79   public:
80         typedef std::set<AudioPort *> PortSet;
81
82         PortExportChannel ();
83         void set_max_buffer_size(framecnt_t frames);
84
85         void read (Sample const *& data, framecnt_t frames) const;
86         bool empty () const { return ports.empty(); }
87
88         void get_state (XMLNode * node) const;
89         void set_state (XMLNode * node, Session & session);
90
91         bool operator< (ExportChannel const & other) const;
92
93         void add_port (AudioPort * port) { ports.insert (port); }
94         PortSet const & get_ports () { return ports; }
95
96   private:
97         PortSet ports;
98         boost::scoped_array<Sample> buffer;
99         framecnt_t buffer_size;
100 };
101
102 /// Handles RegionExportChannels and does actual reading from region
103 class RegionExportChannelFactory 
104 {
105   public:
106         enum Type {
107                 Raw,
108                 Fades,
109                 Processed
110         };
111
112         RegionExportChannelFactory (Session * session, AudioRegion const & region, AudioTrack & track, Type type);
113         ~RegionExportChannelFactory ();
114
115         ExportChannelPtr create (uint32_t channel);
116         void read (uint32_t channel, Sample const *& data, framecnt_t frames_to_read);
117
118   private:
119
120         int new_cycle_started (framecnt_t) { buffers_up_to_date = false; return 0; }
121         void update_buffers (framecnt_t frames);
122
123         AudioRegion const & region;
124         AudioTrack & track;
125         Type type;
126
127         framecnt_t frames_per_cycle;
128         size_t n_channels;
129         BufferSet buffers;
130         bool buffers_up_to_date;
131         framecnt_t region_start;
132         framecnt_t position;
133
134         boost::scoped_array<Sample> mixdown_buffer;
135         boost::scoped_array<Sample> gain_buffer;
136
137         PBD::ScopedConnection export_connection;
138 };
139
140 /// Export channel that reads from region channel
141 class RegionExportChannel : public ExportChannel
142 {
143         friend class RegionExportChannelFactory;
144
145   public:
146         void read (Sample const *& data, framecnt_t frames_to_read) const { factory.read (channel, data, frames_to_read); }
147         void get_state (XMLNode * /*node*/) const {};
148         void set_state (XMLNode * /*node*/, Session & /*session*/) {};
149         bool empty () const { return false; }
150         // Region export should never have duplicate channels, so there need not be any semantics here
151         bool operator< (ExportChannel const & other) const { return this < &other; }
152
153   private:
154
155         RegionExportChannel (RegionExportChannelFactory & factory, uint32_t channel)
156                 : factory (factory)
157                 , channel (channel)
158         {}
159
160         RegionExportChannelFactory & factory;
161         uint32_t channel;
162 };
163
164 /// Export channel for exporting from different positions in a route
165 class RouteExportChannel : public ExportChannel
166 {
167         class ProcessorRemover; // fwd declaration
168
169   public:
170         RouteExportChannel(boost::shared_ptr<CapturingProcessor> processor, size_t channel,
171                            boost::shared_ptr<ProcessorRemover> remover);
172         ~RouteExportChannel();
173
174         static void create_from_route(std::list<ExportChannelPtr> & result, Route & route);
175
176   public: // ExportChannel interface
177         void set_max_buffer_size(framecnt_t frames);
178
179         void read (Sample const *& data, framecnt_t frames) const;
180         bool empty () const { return false; }
181
182         void get_state (XMLNode * node) const;
183         void set_state (XMLNode * node, Session & session);
184
185         bool operator< (ExportChannel const & other) const;
186
187   private:
188
189         // Removes the processor from the track when deleted
190         class ProcessorRemover {
191           public:
192                 ProcessorRemover (Route & route, boost::shared_ptr<CapturingProcessor> processor)
193                         : route (route), processor (processor) {}
194                 ~ProcessorRemover();
195           private:
196                 Route & route;
197                 boost::shared_ptr<CapturingProcessor> processor;
198         };
199
200         boost::shared_ptr<CapturingProcessor> processor;
201         size_t channel;
202         // Each channel keeps a ref to the remover. Last one alive
203         // will cause the processor to be removed on deletion.
204         boost::shared_ptr<ProcessorRemover> remover;
205 };
206
207 } // namespace ARDOUR
208
209 #endif