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) {
}
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) {
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;
}
}
- 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;
}
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);
}
_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); \
} \
}
inplace = false;
}
- DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("%1 in %2 out %3 MIDI %4 bufs %5 (available %6) Inplace: %7\n",
+ DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("%1 in %2 out %3 MIDI %4 bufs %5 (available %6) InBus %7 OutBus %8 Inplace: %9 var-i/o %10 %11\n",
name(), input_channels, output_channels, _has_midi_input,
- bufs.count(), bufs.available(), inplace));
+ bufs.count(), bufs.available(),
+ configured_input_busses, configured_output_busses, inplace, variable_inputs, variable_outputs));
/* the apparent number of buffers matches our input configuration, but we know that the bufferset
* has the capacity to handle our outputs.
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;
+ if (variable_outputs || (output_elements == configured_output_busses && configured_output_busses == 1)) {
+ cnt = output_channels;
+ } else {
+ cnt = std::min (remain, bus_outputs[bus]);
+ }
assert (cnt > 0);
buffers->mNumberBuffers = cnt;
}
}
} else {
- error << string_compose (_("AU: render error for %1, bus %2 status = %2"), name(), bus, err) << endmsg;
+ DEBUG_TRACE (DEBUG::AudioUnits, string_compose (_("AU: render error for %1, bus %2 status = %3\n"), name(), bus, err));
+ error << string_compose (_("AU: render error for %1, bus %2 status = %3"), name(), bus, err) << endmsg;
ok = false;
break;
}
return kAudioUnitErr_CannotDoInCurrentContext;
}
- Timecode::BBT_Time bbt;
TempoMetric metric = tmap.metric_at (_session.transport_frame() + input_offset);
- tmap.bbt_time (_session.transport_frame() + input_offset, bbt);
+ Timecode::BBT_Time bbt = _session.tempo_map().bbt_at_frame (_session.transport_frame() + input_offset);
if (outCurrentBeat) {
+ const double ppq_scaling = metric.meter().note_divisor() / 4.0;
float beat;
- beat = metric.meter().divisions_per_bar() * bbt.bars;
- beat += bbt.beats;
+ beat = metric.meter().divisions_per_bar() * (bbt.bars - 1);
+ beat += (bbt.beats - 1);
beat += bbt.ticks / Timecode::BBT_Time::ticks_per_beat;
- *outCurrentBeat = beat;
+ *outCurrentBeat = beat * ppq_scaling;
}
if (outCurrentTempo) {
return kAudioUnitErr_CannotDoInCurrentContext;
}
- Timecode::BBT_Time bbt;
TempoMetric metric = tmap.metric_at (_session.transport_frame() + input_offset);
- tmap.bbt_time (_session.transport_frame() + input_offset, bbt);
+ Timecode::BBT_Time bbt = _session.tempo_map().bbt_at_frame (_session.transport_frame() + input_offset);
if (outDeltaSampleOffsetToNextBeat) {
if (bbt.ticks == 0) {
/* on the beat */
*outDeltaSampleOffsetToNextBeat = 0;
} else {
- *outDeltaSampleOffsetToNextBeat = (UInt32)
- floor (((Timecode::BBT_Time::ticks_per_beat - bbt.ticks)/Timecode::BBT_Time::ticks_per_beat) * // fraction of a beat to next beat
- metric.tempo().frames_per_beat (_session.frame_rate())); // frames per beat
+ double const beat_frac_to_next = (Timecode::BBT_Time::ticks_per_beat - bbt.ticks) / Timecode::BBT_Time::ticks_per_beat;
+ *outDeltaSampleOffsetToNextBeat = tmap.frame_at_beat (tmap.beat_at_frame (_session.transport_frame() + input_offset) + beat_frac_to_next);
}
}
if (outCycleStartBeat) {
TempoMetric metric = tmap.metric_at (loc->start() + input_offset);
- _session.tempo_map().bbt_time (loc->start(), bbt);
+ bbt = _session.tempo_map().bbt_at_frame (loc->start() + input_offset);
float beat;
beat = metric.meter().divisions_per_bar() * bbt.bars;
if (outCycleEndBeat) {
TempoMetric metric = tmap.metric_at (loc->end() + input_offset);
- _session.tempo_map().bbt_time (loc->end(), bbt);
+ bbt = _session.tempo_map().bbt_at_frame (loc->end() + input_offset);
float beat;
beat = metric.meter().divisions_per_bar() * bbt.bars;
if (pid < bus_inputs[bus]) {
id = pid;
ss << _bus_name_in[bus];
+ ss << " / Bus " << (1 + bus);
break;
}
pid -= bus_inputs[bus];
if (pid < bus_outputs[bus]) {
id = pid;
ss << _bus_name_out[bus];
+ ss << " / Bus " << (1 + bus);
break;
}
pid -= bus_outputs[bus];
void
AUPlugin::add_state (XMLNode* root) const
{
- LocaleGuard lg (X_("C"));
+ LocaleGuard lg;
CFDataRef xmlData;
CFPropertyListRef propertyList;
{
int ret = -1;
CFPropertyListRef propertyList;
- LocaleGuard lg (X_("C"));
+ LocaleGuard lg;
if (node.name() != state_node_name()) {
error << _("Bad node sent to AUPlugin::set_state") << endmsg;
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 ();
}
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) {
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));
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)
{
}
//initial version has incorrectly stored i/o info, and/or garbage chars.
- const XMLProperty* version = root->property(X_("version"));
+ XMLProperty const * version = root->property(X_("version"));
if (! ((version != NULL) && (version->value() == X_(AU_CACHE_VERSION)))) {
error << "au_cache is not correct version. AU plugins will be re-scanned" << endmsg;
return -1;
const XMLNode* gchild;
const XMLNodeList gchildren = child->children();
- const XMLProperty* prop = child->property (X_("id"));
+ XMLProperty const * prop = child->property (X_("id"));
if (!prop) {
continue;
int in;
int out;
- const XMLProperty* iprop;
- const XMLProperty* oprop;
+ XMLProperty const * iprop;
+ XMLProperty const * oprop;
if (((iprop = gchild->property (X_("in"))) != 0) &&
((oprop = gchild->property (X_("out"))) != 0)) {