Optimize Plugin connect & run API, use const maps
[ardour.git] / libs / ardour / ardour / audio_unit.h
1 /*
2     Copyright (C) 2006 Paul Davis
3     Written by Taybin Rutkin
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_audio_unit_h__
22 #define __ardour_audio_unit_h__
23
24 #include <stdint.h>
25 #include <boost/shared_ptr.hpp>
26
27 #include <list>
28 #include <set>
29 #include <string>
30 #include <vector>
31 #include <map>
32
33 #include "ardour/plugin.h"
34
35 #include <AudioUnit/AudioUnit.h>
36 #include <AudioUnit/AudioUnitProperties.h>
37 #include "AUParamInfo.h"
38
39 #include <boost/shared_ptr.hpp>
40
41 class CAComponent;
42 class CAAudioUnit;
43 class CAComponentDescription;
44 struct AudioBufferList;
45
46 namespace ARDOUR {
47
48 class AudioEngine;
49 class Session;
50
51 struct LIBARDOUR_API AUParameterDescriptor : public ParameterDescriptor {
52         // additional fields to make operations more efficient
53         AudioUnitParameterID id;
54         AudioUnitScope scope;
55         AudioUnitElement element;
56         bool automatable;
57         AudioUnitParameterUnit au_unit;
58 };
59
60 class LIBARDOUR_API AUPlugin : public ARDOUR::Plugin
61 {
62   public:
63         AUPlugin (AudioEngine& engine, Session& session, boost::shared_ptr<CAComponent> comp);
64         AUPlugin (const AUPlugin& other);
65         virtual ~AUPlugin ();
66
67         std::string unique_id () const;
68         const char * label () const;
69         const char * name () const { return _info->name.c_str(); }
70         const char * maker () const { return _info->creator.c_str(); }
71         uint32_t parameter_count () const;
72         float default_value (uint32_t port);
73         samplecnt_t signal_latency() const;
74         void set_parameter (uint32_t which, float val);
75         float get_parameter (uint32_t which) const;
76
77         PluginOutputConfiguration possible_output () const { return _output_configs; }
78
79         int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
80         uint32_t nth_parameter (uint32_t which, bool& ok) const;
81         void activate ();
82         void deactivate ();
83         void flush ();
84         int set_block_size (pframes_t nframes);
85
86         int connect_and_run (BufferSet& bufs,
87                         samplepos_t start, samplepos_t end, double speed,
88                         ChanMapping const& in, ChanMapping const& out,
89                         pframes_t nframes, samplecnt_t offset);
90         std::set<Evoral::Parameter> automatable() const;
91         std::string describe_parameter (Evoral::Parameter);
92         IOPortDescription describe_io_port (DataType dt, bool input, uint32_t id) const;
93         std::string state_node_name () const { return "audiounit"; }
94         void print_parameter (uint32_t, char*, uint32_t len) const;
95
96         bool parameter_is_audio (uint32_t) const;
97         bool parameter_is_control (uint32_t) const;
98         bool parameter_is_input (uint32_t) const;
99         bool parameter_is_output (uint32_t) const;
100
101         void set_info (PluginInfoPtr);
102
103         int set_state(const XMLNode& node, int);
104
105         bool load_preset (PresetRecord);
106         std::string current_preset() const;
107
108         bool has_editor () const;
109
110         bool can_support_io_configuration (const ChanCount& in, ChanCount& out, ChanCount* imprecise);
111         ChanCount output_streams() const;
112         ChanCount input_streams() const;
113         bool configure_io (ChanCount in, ChanCount out);
114         bool requires_fixed_size_buffers() const;
115
116         void set_fixed_size_buffers (bool yn) {
117                 _requires_fixed_size_buffers = yn;
118         }
119
120         boost::shared_ptr<CAAudioUnit> get_au () { return unit; }
121         boost::shared_ptr<CAComponent> get_comp () const { return comp; }
122
123         OSStatus render_callback(AudioUnitRenderActionFlags *ioActionFlags,
124                                  const AudioTimeStamp       *inTimeStamp,
125                                  UInt32                      inBusNumber,
126                                  UInt32                      inNumberSamples,
127                                  AudioBufferList*            ioData);
128
129         /* "host" callbacks */
130
131         OSStatus get_beat_and_tempo_callback (Float64* outCurrentBeat,
132                                               Float64* outCurrentTempo);
133
134         OSStatus get_musical_time_location_callback (UInt32*  outDeltaSampleOffsetToNextBeat,
135                                                      Float32*  outTimeSig_Numerator,
136                                                      UInt32*   outTimeSig_Denominator,
137                                                      Float64*  outCurrentMeasureDownBeat);
138
139         OSStatus get_transport_state_callback (Boolean*  outIsPlaying,
140                                                Boolean*  outTransportStateChanged,
141                                                Float64*  outCurrentSampleInTimeLine,
142                                                Boolean*  outIsCycling,
143                                                Float64*  outCycleStartBeat,
144                                                Float64*  outCycleEndBeat);
145
146         static std::string maybe_fix_broken_au_id (const std::string&);
147
148         /* this MUST be called from thread in which you want to receive notifications
149            about parameter changes.
150         */
151         int create_parameter_listener (AUEventListenerProc callback, void *arg, float interval_secs);
152         /* these can be called from any thread but SHOULD be called from the same thread
153            that will receive parameter change notifications.
154         */
155         int listen_to_parameter (uint32_t param_id);
156         int end_listen_to_parameter (uint32_t param_id);
157
158
159   protected:
160         std::string do_save_preset (std::string name);
161         void do_remove_preset (std::string);
162
163   private:
164         void find_presets ();
165
166         boost::shared_ptr<CAComponent> comp;
167         boost::shared_ptr<CAAudioUnit> unit;
168
169         bool initialized;
170         int32_t input_channels;
171         int32_t output_channels;
172         std::vector<std::pair<int,int> > io_configs;
173         samplecnt_t _last_nframes;
174         mutable volatile guint _current_latency;
175         bool _requires_fixed_size_buffers;
176         AudioBufferList* buffers;
177         bool _has_midi_input;
178         bool _has_midi_output;
179         PluginOutputConfiguration _output_configs;
180
181         /* despite all the cool work that apple did on their AU preset
182            system, they left factory presets and user presets as two
183            entirely different kinds of things, handled by two entirely
184            different parts of the API. Resolve this.
185         */
186
187         /* XXX these two maps should really be shared across all instances of this AUPlugin */
188
189         typedef std::map<std::string,std::string> UserPresetMap;
190         UserPresetMap user_preset_map;
191         typedef std::map<std::string,int> FactoryPresetMap;
192         FactoryPresetMap factory_preset_map;
193
194         UInt32 global_elements;
195         UInt32 output_elements;
196         UInt32 input_elements;
197
198         bool variable_inputs;
199         bool variable_outputs;
200
201         uint32_t configured_input_busses;
202         uint32_t configured_output_busses;
203
204         uint32_t *bus_inputs;
205         uint32_t *bus_outputs;
206         std::vector <std::string> _bus_name_in;
207         std::vector <std::string> _bus_name_out;
208
209         int set_stream_format (int scope, uint32_t bus, AudioStreamBasicDescription&);
210         void discover_parameters ();
211         void add_state (XMLNode *) const;
212
213         typedef std::map<uint32_t, uint32_t> ParameterMap;
214         ParameterMap parameter_map;
215         uint32_t   input_maxbuf;
216         samplecnt_t input_offset;
217         samplecnt_t *cb_offsets;
218         BufferSet* input_buffers;
219         ChanMapping * input_map;
220         samplecnt_t samples_processed;
221         uint32_t   audio_input_cnt;
222
223         std::vector<AUParameterDescriptor> descriptors;
224         AUEventListenerRef _parameter_listener;
225         void * _parameter_listener_arg;
226         void init ();
227
228         void discover_factory_presets ();
229
230         samplepos_t transport_sample;
231         float      transport_speed;
232         float      last_transport_speed;
233
234         static void _parameter_change_listener (void* /*arg*/, void* /*src*/, const AudioUnitEvent* event, UInt64 host_time, Float32 new_value);
235         void parameter_change_listener (void* /*arg*/, void* /*src*/, const AudioUnitEvent* event, UInt64 host_time, Float32 new_value);
236 };
237
238 typedef boost::shared_ptr<AUPlugin> AUPluginPtr;
239
240 struct LIBARDOUR_API AUPluginCachedInfo {
241         std::vector<std::pair<int,int> > io_configs;
242 };
243
244 class LIBARDOUR_API AUPluginInfo : public PluginInfo {
245   public:
246          AUPluginInfo (boost::shared_ptr<CAComponentDescription>);
247         ~AUPluginInfo ();
248
249         PluginPtr load (Session& session);
250
251         std::vector<Plugin::PresetRecord> get_presets (bool user_only) const;
252
253         bool needs_midi_input () const;
254         bool is_effect_without_midi_input () const;
255         bool is_effect_with_midi_input () const;
256
257         /* note: AU's have an explicit way to prompt for instrument/fx category */
258         bool is_effect () const;
259         bool is_instrument () const;
260         bool is_utility () const;
261
262         AUPluginCachedInfo cache;
263
264         bool reconfigurable_io() const { return true; }
265
266         static void clear_cache ();
267         static PluginInfoList* discover (bool scan_only);
268         static bool au_get_crashlog (std::string &msg);
269         static std::string stringify_descriptor (const CAComponentDescription&);
270
271         static int load_cached_info ();
272
273   private:
274         boost::shared_ptr<CAComponentDescription> descriptor;
275         UInt32 version;
276         static FILE * _crashlog_fd;
277         static bool _scan_only;
278
279         static void au_start_crashlog (void);
280         static void au_remove_crashlog (void);
281         static void au_crashlog (std::string);
282
283         static void discover_music (PluginInfoList&);
284         static void discover_fx (PluginInfoList&);
285         static void discover_generators (PluginInfoList&);
286         static void discover_instruments (PluginInfoList&);
287         static void discover_by_description (PluginInfoList&, CAComponentDescription&);
288         static Glib::ustring au_cache_path ();
289
290         typedef std::map<std::string,AUPluginCachedInfo> CachedInfoMap;
291         static CachedInfoMap cached_info;
292
293         static int cached_io_configuration (const std::string&, UInt32, CAComponent&, AUPluginCachedInfo&, const std::string& name);
294         static void add_cached_info (const std::string&, AUPluginCachedInfo&);
295         static void save_cached_info ();
296 };
297
298 typedef boost::shared_ptr<AUPluginInfo> AUPluginInfoPtr;
299
300 } // namespace ARDOUR
301
302 #endif // __ardour_audio_unit_h__