allow to customize variable i/o plugin inputs
[ardour.git] / libs / ardour / audio_unit.cc
index d53a17ca35c4856fa7ff3866a60ae211eabc71c7..44080a0bc80ef8b13697c4df1f285ea62e00855b 100644 (file)
@@ -605,15 +605,14 @@ AUPlugin::init ()
        bus_outputs = (uint32_t*) calloc (output_elements, sizeof(uint32_t));
 
        for (size_t i = 0; i < output_elements; ++i) {
-               AudioUnitReset (unit->AU(), kAudioUnitScope_Output, i);
+               unit->Reset (kAudioUnitScope_Output, i);
                AudioStreamBasicDescription fmt;
-               UInt32 sz = sizeof(AudioStreamBasicDescription);
-               err = AudioUnitGetProperty(unit->AU(), kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, i, &fmt, &sz);
+               err = unit->GetFormat (kAudioUnitScope_Output, i, fmt);
                if (err == noErr) {
                        bus_outputs[i] = fmt.mChannelsPerFrame;
                }
                CFStringRef name;
-               sz = sizeof (CFStringRef);
+               UInt32 sz = sizeof (CFStringRef);
                if (AudioUnitGetProperty (unit->AU(), kAudioUnitProperty_ElementName, kAudioUnitScope_Output,
                                        i, &name, &sz) == noErr
                                && sz > 0) {
@@ -625,15 +624,14 @@ AUPlugin::init ()
        }
 
        for (size_t i = 0; i < input_elements; ++i) {
-               AudioUnitReset (unit->AU(), kAudioUnitScope_Input, i);
+               unit->Reset (kAudioUnitScope_Input, i);
                AudioStreamBasicDescription fmt;
-               UInt32 sz = sizeof(AudioStreamBasicDescription);
-               err = AudioUnitGetProperty(unit->AU(), kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, i, &fmt, &sz);
+               err = unit->GetFormat (kAudioUnitScope_Input, i, fmt);
                if (err == noErr) {
                        bus_inputs[i] = fmt.mChannelsPerFrame;
                }
                CFStringRef name;
-               sz = sizeof (CFStringRef);
+               UInt32 sz = sizeof (CFStringRef);
                if (AudioUnitGetProperty (unit->AU(), kAudioUnitProperty_ElementName, kAudioUnitScope_Input,
                                        i, &name, &sz) == noErr
                                && sz > 0) {
@@ -1128,17 +1126,17 @@ AUPlugin::configure_io (ChanCount in, ChanCount out)
        configured_output_busses = 0;
        /* reset busses */
        for (size_t i = 0; i < output_elements; ++i) {
-               AudioUnitReset (unit->AU(), kAudioUnitScope_Output, i);
+               unit->Reset (kAudioUnitScope_Output, i);
        }
        for (size_t i = 0; i < input_elements; ++i) {
-               AudioUnitReset (unit->AU(), kAudioUnitScope_Input, i);
+               unit->Reset (kAudioUnitScope_Input, i);
        }
 
        /* now assign the channels to available busses */
        uint32_t used_in = 0;
        uint32_t used_out = 0;
 
-       if (variable_inputs) {
+       if (variable_inputs || input_elements == 1) {
                // we only ever use the first bus
                if (input_elements > 1) {
                        warning << string_compose (_("AU %1 has multiple input busses and variable port count."), name()) << endmsg;
@@ -1167,7 +1165,7 @@ AUPlugin::configure_io (ChanCount in, ChanCount out)
                }
        }
 
-       if (variable_outputs) {
+       if (variable_outputs || output_elements == 1) {
                if (output_elements > 1) {
                        warning << string_compose (_("AU %1 has multiple output busses and variable port count."), name()) << endmsg;
                }
@@ -1263,7 +1261,7 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
                                                        name(), io_configs.size(), in, out));
 
 #if 0
-       printf ("AU I/O Configs %s %d\n", name().c_str(), io_configs.size());
+       printf ("AU I/O Configs %s %d\n", name(), io_configs.size());
        for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) {
                printf ("- I/O  %d / %d\n", i->first, i->second);
        }
@@ -1345,7 +1343,7 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
   _output_configs.insert (0);
 
 #define UPTO(nch) {                                \
-  for (int n = 1; n < nch; ++n) {                  \
+  for (int n = 1; n <= nch; ++n) {                 \
     _output_configs.insert (n);                    \
   }                                                \
 }
@@ -1653,7 +1651,7 @@ AUPlugin::connect_and_run (BufferSet& bufs, ChanMapping in_map, ChanMapping out_
        uint32_t busoff = 0;
        uint32_t remain = output_channels;
        for (uint32_t bus = 0; remain > 0 && bus < configured_output_busses; ++bus) {
-               uint32_t cnt = std::min (remain, bus_outputs[bus]);
+               uint32_t cnt = variable_outputs ? output_channels : std::min (remain, bus_outputs[bus]); // XXX
                assert (cnt > 0);
 
                buffers->mNumberBuffers = cnt;
@@ -1958,6 +1956,7 @@ AUPlugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id) const
                                if (pid < bus_inputs[bus]) {
                                        id = pid;
                                        ss << _bus_name_in[bus];
+                                       ss << " / Bus " << (1 + bus);
                                        break;
                                }
                                pid -= bus_inputs[bus];
@@ -1969,6 +1968,7 @@ AUPlugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id) const
                                if (pid < bus_outputs[bus]) {
                                        id = pid;
                                        ss << _bus_name_out[bus];
+                                       ss << " / Bus " << (1 + bus);
                                        break;
                                }
                                pid -= bus_outputs[bus];
@@ -2698,6 +2698,8 @@ AUPluginInfo::discover (bool scan_only)
 
        if (!Glib::file_test (au_cache_path(), Glib::FILE_TEST_EXISTS)) {
                ARDOUR::BootMessage (_("Discovering AudioUnit plugins (could take some time ...)"));
+               // flush RAM cache -- after clear_cache()
+               cached_info.clear();
        }
        // create crash log file
        au_start_crashlog ();
@@ -3038,17 +3040,21 @@ AUPluginInfo::cached_io_configuration (const std::string& unique_id,
        }
 
        if (ret > 0) {
-
-               /* no explicit info available, so default to 1in/1out */
-
-               /* XXX this is wrong. we should be indicating wildcard values */
-
+               /* AU is expected to deal with same channel valance in and out */
                cinfo.io_configs.push_back (pair<int,int> (-1, -1));
-
        } else {
-               /* store each configuration */
-               if (comp.Desc().IsGenerator() || comp.Desc().IsMusicDevice()) {
-                       // incrementally add busses
+               /* CAAudioUnit::GetChannelInfo silently merges bus formats
+                * check if this was the case and if so, add
+                * bus configs as incremental options.
+                */
+               Boolean* isWritable = 0;
+               UInt32  dataSize = 0;
+               OSStatus result = AudioUnitGetPropertyInfo (unit.AU(),
+                               kAudioUnitProperty_SupportedNumChannels,
+                               kAudioUnitScope_Global, 0,
+                               &dataSize, isWritable);
+               if (result != noErr && (comp.Desc().IsGenerator() || comp.Desc().IsMusicDevice())) {
+                       /* incrementally add busses */
                        int in = 0;
                        int out = 0;
                        for (uint32_t n = 0; n < cnt; ++n) {
@@ -3057,6 +3063,7 @@ AUPluginInfo::cached_io_configuration (const std::string& unique_id,
                                cinfo.io_configs.push_back (pair<int,int> (in, out));
                        }
                } else {
+                       /* store each configuration */
                        for (uint32_t n = 0; n < cnt; ++n) {
                                cinfo.io_configs.push_back (pair<int,int> (channel_info[n].inChannels,
                                                        channel_info[n].outChannels));
@@ -3072,6 +3079,17 @@ AUPluginInfo::cached_io_configuration (const std::string& unique_id,
        return 0;
 }
 
+void
+AUPluginInfo::clear_cache ()
+{
+       const string& fn = au_cache_path();
+       if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
+               ::g_unlink(fn.c_str());
+       }
+       // keep cached_info in RAM until restart or re-scan
+       cached_info.clear();
+}
+
 void
 AUPluginInfo::add_cached_info (const std::string& id, AUPluginCachedInfo& cinfo)
 {