Single instance AUs only, use variable i/o
[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         framecnt_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                              ChanMapping in, ChanMapping out,
88                              pframes_t nframes, framecnt_t offset);
89         std::set<Evoral::Parameter> automatable() const;
90         std::string describe_parameter (Evoral::Parameter);
91         IOPortDescription describe_io_port (DataType dt, bool input, uint32_t id) const;
92         std::string state_node_name () const { return "audiounit"; }
93         void print_parameter (uint32_t, char*, uint32_t len) const;
94
95         bool parameter_is_audio (uint32_t) const;
96         bool parameter_is_control (uint32_t) const;
97         bool parameter_is_input (uint32_t) const;
98         bool parameter_is_output (uint32_t) const;
99
100         void set_info (PluginInfoPtr);
101
102         int set_state(const XMLNode& node, int);
103
104         bool load_preset (PresetRecord);
105         std::string current_preset() const;
106
107         bool has_editor () const;
108
109         bool can_support_io_configuration (const ChanCount& in, ChanCount& out, ChanCount* imprecise);
110         ChanCount output_streams() const;
111         ChanCount input_streams() const;
112         bool configure_io (ChanCount in, ChanCount out);
113         bool requires_fixed_size_buffers() const;
114
115         void set_fixed_size_buffers (bool yn) {
116                 _requires_fixed_size_buffers = yn;
117         }
118
119         boost::shared_ptr<CAAudioUnit> get_au () { return unit; }
120         boost::shared_ptr<CAComponent> get_comp () const { return comp; }
121
122         OSStatus render_callback(AudioUnitRenderActionFlags *ioActionFlags,
123                                  const AudioTimeStamp       *inTimeStamp,
124                                  UInt32                      inBusNumber,
125                                  UInt32                      inNumberFrames,
126                                  AudioBufferList*            ioData);
127
128         /* "host" callbacks */
129
130         OSStatus get_beat_and_tempo_callback (Float64* outCurrentBeat,
131                                               Float64* outCurrentTempo);
132
133         OSStatus get_musical_time_location_callback (UInt32*  outDeltaSampleOffsetToNextBeat,
134                                                      Float32*  outTimeSig_Numerator,
135                                                      UInt32*   outTimeSig_Denominator,
136                                                      Float64*  outCurrentMeasureDownBeat);
137
138         OSStatus get_transport_state_callback (Boolean*  outIsPlaying,
139                                                Boolean*  outTransportStateChanged,
140                                                Float64*  outCurrentSampleInTimeLine,
141                                                Boolean*  outIsCycling,
142                                                Float64*  outCycleStartBeat,
143                                                Float64*  outCycleEndBeat);
144
145         static std::string maybe_fix_broken_au_id (const std::string&);
146
147         /* this MUST be called from thread in which you want to receive notifications
148            about parameter changes.
149         */
150         int create_parameter_listener (AUEventListenerProc callback, void *arg, float interval_secs);
151         /* these can be called from any thread but SHOULD be called from the same thread
152            that will receive parameter change notifications.
153         */
154         int listen_to_parameter (uint32_t param_id);
155         int end_listen_to_parameter (uint32_t param_id);
156
157
158   protected:
159         std::string do_save_preset (std::string name);
160         void do_remove_preset (std::string);
161
162   private:
163         void find_presets ();
164
165         boost::shared_ptr<CAComponent> comp;
166         boost::shared_ptr<CAAudioUnit> unit;
167
168         bool initialized;
169         int32_t input_channels;
170         int32_t output_channels;
171         std::vector<std::pair<int,int> > io_configs;
172         pframes_t _current_block_size;
173         framecnt_t _last_nframes;
174         bool _requires_fixed_size_buffers;
175         AudioBufferList* buffers;
176         bool _has_midi_input;
177         bool _has_midi_output;
178         PluginOutputConfiguration _output_configs;
179
180         /* despite all the cool work that apple did on their AU preset
181            system, they left factory presets and user presets as two
182            entirely different kinds of things, handled by two entirely
183            different parts of the API. Resolve this.
184         */
185
186         /* XXX these two maps should really be shared across all instances of this AUPlugin */
187
188         typedef std::map<std::string,std::string> UserPresetMap;
189         UserPresetMap user_preset_map;
190         typedef std::map<std::string,int> FactoryPresetMap;
191         FactoryPresetMap factory_preset_map;
192
193         UInt32 global_elements;
194         UInt32 output_elements;
195         UInt32 input_elements;
196
197         bool variable_inputs;
198         bool variable_outputs;
199
200         uint32_t configured_input_busses;
201         uint32_t configured_output_busses;
202
203         uint32_t *bus_inputs;
204         uint32_t *bus_outputs;
205         std::vector <std::string> _bus_name_in;
206         std::vector <std::string> _bus_name_out;
207
208         int set_stream_format (int scope, uint32_t bus, AudioStreamBasicDescription&);
209         void discover_parameters ();
210         void add_state (XMLNode *) const;
211
212         typedef std::map<uint32_t, uint32_t> ParameterMap;
213         ParameterMap parameter_map;
214         uint32_t   input_maxbuf;
215         framecnt_t input_offset;
216         framecnt_t *cb_offsets;
217         BufferSet* input_buffers;
218         ChanMapping * input_map;
219         framecnt_t frames_processed;
220         uint32_t   audio_input_cnt;
221
222         std::vector<AUParameterDescriptor> descriptors;
223         AUEventListenerRef _parameter_listener;
224         void * _parameter_listener_arg;
225         void init ();
226
227         void discover_factory_presets ();
228
229         bool      last_transport_rolling;
230         float     last_transport_speed;
231
232         static void _parameter_change_listener (void* /*arg*/, void* /*src*/, const AudioUnitEvent* event, UInt64 host_time, Float32 new_value);
233         void parameter_change_listener (void* /*arg*/, void* /*src*/, const AudioUnitEvent* event, UInt64 host_time, Float32 new_value);
234 };
235
236 typedef boost::shared_ptr<AUPlugin> AUPluginPtr;
237
238 struct LIBARDOUR_API AUPluginCachedInfo {
239         std::vector<std::pair<int,int> > io_configs;
240 };
241
242 class LIBARDOUR_API AUPluginInfo : public PluginInfo {
243   public:
244          AUPluginInfo (boost::shared_ptr<CAComponentDescription>);
245         ~AUPluginInfo ();
246
247         PluginPtr load (Session& session);
248
249         std::vector<Plugin::PresetRecord> get_presets (bool user_only) const;
250
251         bool needs_midi_input () const;
252         bool is_effect () const;
253         bool is_effect_without_midi_input () const;
254         bool is_effect_with_midi_input () const;
255         bool is_instrument () const;
256
257         AUPluginCachedInfo cache;
258
259         bool reconfigurable_io() const { return true; }
260
261         static PluginInfoList* discover (bool scan_only);
262         static bool au_get_crashlog (std::string &msg);
263         static std::string stringify_descriptor (const CAComponentDescription&);
264
265         static int load_cached_info ();
266
267   private:
268         boost::shared_ptr<CAComponentDescription> descriptor;
269         UInt32 version;
270         static FILE * _crashlog_fd;
271         static bool _scan_only;
272
273         static void au_start_crashlog (void);
274         static void au_remove_crashlog (void);
275         static void au_crashlog (std::string);
276
277         static void discover_music (PluginInfoList&);
278         static void discover_fx (PluginInfoList&);
279         static void discover_generators (PluginInfoList&);
280         static void discover_instruments (PluginInfoList&);
281         static void discover_by_description (PluginInfoList&, CAComponentDescription&);
282         static Glib::ustring au_cache_path ();
283
284         typedef std::map<std::string,AUPluginCachedInfo> CachedInfoMap;
285         static CachedInfoMap cached_info;
286
287         static int cached_io_configuration (const std::string&, UInt32, CAComponent&, AUPluginCachedInfo&, const std::string& name);
288         static void add_cached_info (const std::string&, AUPluginCachedInfo&);
289         static void save_cached_info ();
290 };
291
292 typedef boost::shared_ptr<AUPluginInfo> AUPluginInfoPtr;
293
294 } // namespace ARDOUR
295
296 #endif // __ardour_audio_unit_h__