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