|
- /*
- ==============================================================================
-
- This file is part of the JUCE library - "Jules' Utility Class Extensions"
- Copyright 2004-7 by Raw Material Software ltd.
-
- ------------------------------------------------------------------------------
-
- JUCE can be redistributed and/or modified under the terms of the
- GNU General Public License, as published by the Free Software Foundation;
- either version 2 of the License, or (at your option) any later version.
-
- JUCE is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with JUCE; if not, visit www.gnu.org/licenses or write to the
- Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- Boston, MA 02111-1307 USA
-
- ------------------------------------------------------------------------------
-
- If you'd like to release a closed-source product which uses JUCE, commercial
- licenses are also available: visit www.rawmaterialsoftware.com/juce for
- more information.
-
- ==============================================================================
- */
-
- #if ! (defined (LINUX) || defined (_WIN32))
-
- #include <Carbon/Carbon.h>
- #include <AudioToolbox/AudioToolbox.h>
- #include <AudioUnit/AudioUnitCarbonView.h>
-
- #include "../../../../../juce.h"
- #include "juce_AudioUnitPluginFormat.h"
- #include "../juce_PluginDescription.h"
-
- #if JUCE_PLUGINHOST_AU && JUCE_MAC
-
- BEGIN_JUCE_NAMESPACE
- extern void juce_callAnyTimersSynchronously();
- extern bool juce_isHIViewCreatedByJuce (HIViewRef view);
- extern bool juce_isWindowCreatedByJuce (WindowRef window);
- END_JUCE_NAMESPACE
-
- #if MACOS_10_3_OR_EARLIER
- #define kAudioUnitType_Generator 'augn'
- #endif
-
- // Change this to disable logging of various activities
- #ifndef AU_LOGGING
- #define AU_LOGGING 1
- #endif
-
- #if AU_LOGGING
- #define log(a) Logger::writeToLog(a);
- #else
- #define log(a)
- #endif
-
- static int insideCallback = 0;
-
- //==============================================================================
- class AudioUnitPluginWindow;
-
- //==============================================================================
- class AudioUnitPluginInstance : public AudioPluginInstance
- {
- public:
- //==============================================================================
- ~AudioUnitPluginInstance();
-
- //==============================================================================
- // AudioPluginInstance methods:
-
- const String getName() const { return pluginName; }
- const String getManufacturer() const { return manufacturer; }
- const String getVersion() const { return version; }
- bool isInstrument() const { return componentDesc.componentType == kAudioUnitType_MusicDevice; }
- const String getCategory() const;
- const String getFormatName() const { return "AudioUnit"; }
- const File getFile() const { return file; }
- int getUID() const { return file.hashCode(); }
- bool acceptsMidi() const { return wantsMidiMessages; }
- bool producesMidi() const { return false; }
-
- //==============================================================================
- // AudioProcessor methods:
-
- void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock);
- void releaseResources();
- void processBlock (AudioSampleBuffer& buffer,
- MidiBuffer& midiMessages);
-
- AudioProcessorEditor* createEditor();
-
- const String getInputChannelName (const int index) const;
- bool isInputChannelStereoPair (int index) const;
-
- const String getOutputChannelName (const int index) const;
- bool isOutputChannelStereoPair (int index) const;
-
- //==============================================================================
- int getNumParameters();
- float getParameter (int index);
- void setParameter (int index, float newValue);
- const String getParameterName (int index);
- const String getParameterText (int index);
- bool isParameterAutomatable (int index) const;
-
- //==============================================================================
- int getNumPrograms();
- int getCurrentProgram();
- void setCurrentProgram (int index);
- const String getProgramName (int index);
- void changeProgramName (int index, const String& newName);
-
- //==============================================================================
- void getStateInformation (MemoryBlock& destData);
- void getCurrentProgramStateInformation (MemoryBlock& destData);
- void setStateInformation (const void* data, int sizeInBytes);
- void setCurrentProgramStateInformation (const void* data, int sizeInBytes);
-
- //==============================================================================
- juce_UseDebuggingNewOperator
-
- private:
- friend class AudioUnitPluginWindow;
- friend class AudioUnitPluginFormat;
-
- ComponentDescription componentDesc;
- String pluginName, manufacturer, version;
- File file;
- CriticalSection lock;
- bool initialised, wantsMidiMessages, wasPlaying;
-
- AudioBufferList* outputBufferList;
- AudioTimeStamp timeStamp;
- AudioSampleBuffer* currentBuffer;
-
- AudioUnit audioUnit;
- Array <int> parameterIds;
-
- //==============================================================================
- bool getComponentDescFromFile (const File& file);
- void initialise();
-
- //==============================================================================
- OSStatus renderGetInput (AudioUnitRenderActionFlags* ioActionFlags,
- const AudioTimeStamp* inTimeStamp,
- UInt32 inBusNumber,
- UInt32 inNumberFrames,
- AudioBufferList* ioData) const;
-
- static OSStatus renderGetInputCallback (void* inRefCon,
- AudioUnitRenderActionFlags* ioActionFlags,
- const AudioTimeStamp* inTimeStamp,
- UInt32 inBusNumber,
- UInt32 inNumberFrames,
- AudioBufferList* ioData)
- {
- return ((AudioUnitPluginInstance*) inRefCon)
- ->renderGetInput (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
- }
-
- OSStatus getBeatAndTempo (Float64* outCurrentBeat, Float64* outCurrentTempo) const;
- OSStatus getMusicalTimeLocation (UInt32* outDeltaSampleOffsetToNextBeat, Float32* outTimeSig_Numerator,
- UInt32* outTimeSig_Denominator, Float64* outCurrentMeasureDownBeat) const;
- OSStatus getTransportState (Boolean* outIsPlaying, Boolean* outTransportStateChanged,
- Float64* outCurrentSampleInTimeLine, Boolean* outIsCycling,
- Float64* outCycleStartBeat, Float64* outCycleEndBeat);
-
- static OSStatus getBeatAndTempoCallback (void* inHostUserData, Float64* outCurrentBeat, Float64* outCurrentTempo)
- {
- return ((AudioUnitPluginInstance*) inHostUserData)->getBeatAndTempo (outCurrentBeat, outCurrentTempo);
- }
-
- static OSStatus getMusicalTimeLocationCallback (void* inHostUserData, UInt32* outDeltaSampleOffsetToNextBeat,
- Float32* outTimeSig_Numerator, UInt32* outTimeSig_Denominator,
- Float64* outCurrentMeasureDownBeat)
- {
- return ((AudioUnitPluginInstance*) inHostUserData)
- ->getMusicalTimeLocation (outDeltaSampleOffsetToNextBeat, outTimeSig_Numerator,
- outTimeSig_Denominator, outCurrentMeasureDownBeat);
- }
-
- static OSStatus getTransportStateCallback (void* inHostUserData, Boolean* outIsPlaying, Boolean* outTransportStateChanged,
- Float64* outCurrentSampleInTimeLine, Boolean* outIsCycling,
- Float64* outCycleStartBeat, Float64* outCycleEndBeat)
- {
- return ((AudioUnitPluginInstance*) inHostUserData)
- ->getTransportState (outIsPlaying, outTransportStateChanged,
- outCurrentSampleInTimeLine, outIsCycling,
- outCycleStartBeat, outCycleEndBeat);
- }
-
- //==============================================================================
- void getNumChannels (int& numIns, int& numOuts)
- {
- numIns = 0;
- numOuts = 0;
-
- AUChannelInfo supportedChannels [128];
- UInt32 supportedChannelsSize = sizeof (supportedChannels);
-
- if (AudioUnitGetProperty (audioUnit, kAudioUnitProperty_SupportedNumChannels, kAudioUnitScope_Global,
- 0, supportedChannels, &supportedChannelsSize) == noErr
- && supportedChannelsSize > 0)
- {
- for (int i = 0; i < supportedChannelsSize / sizeof (AUChannelInfo); ++i)
- {
- numIns = jmax (numIns, supportedChannels[i].inChannels);
- numOuts = jmax (numOuts, supportedChannels[i].outChannels);
- }
- }
- else
- {
- // (this really means the plugin will take any number of ins/outs as long
- // as they are the same)
- numIns = numOuts = 2;
- }
- }
-
- //==============================================================================
- AudioUnitPluginInstance (const File& file);
- };
-
- //==============================================================================
- AudioUnitPluginInstance::AudioUnitPluginInstance (const File& file_)
- : file (file_),
- initialised (false),
- wantsMidiMessages (false),
- audioUnit (0),
- outputBufferList (0),
- currentBuffer (0)
- {
- try
- {
- ++insideCallback;
-
- log (T("Opening AU: ") + file.getFullPathName());
-
- if (getComponentDescFromFile (file))
- {
- ComponentRecord* const comp = FindNextComponent (0, &componentDesc);
-
- if (comp != 0)
- {
- audioUnit = (AudioUnit) OpenComponent (comp);
-
- wantsMidiMessages = componentDesc.componentType == kAudioUnitType_MusicDevice
- || componentDesc.componentType == kAudioUnitType_MusicEffect;
- }
- }
-
- --insideCallback;
- }
- catch (...)
- {
- --insideCallback;
- }
- }
-
- AudioUnitPluginInstance::~AudioUnitPluginInstance()
- {
- {
- const ScopedLock sl (lock);
-
- jassert (insideCallback == 0);
-
- if (audioUnit != 0)
- {
- AudioUnitUninitialize (audioUnit);
- CloseComponent (audioUnit);
- audioUnit = 0;
- }
- }
-
- juce_free (outputBufferList);
- }
-
- bool AudioUnitPluginInstance::getComponentDescFromFile (const File& file)
- {
- zerostruct (componentDesc);
-
- if (! file.hasFileExtension (T(".component")))
- return false;
-
- const String filename (file.getFullPathName());
- const char* const utf8 = filename.toUTF8();
- CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*) utf8,
- strlen (utf8), file.isDirectory());
- if (url != 0)
- {
- CFBundleRef bundleRef = CFBundleCreate (kCFAllocatorDefault, url);
- CFRelease (url);
-
- if (bundleRef != 0)
- {
- CFTypeRef name = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleName"));
-
- if (name != 0 && CFGetTypeID (name) == CFStringGetTypeID())
- pluginName = PlatformUtilities::cfStringToJuceString ((CFStringRef) name);
-
- if (pluginName.isEmpty())
- pluginName = file.getFileNameWithoutExtension();
-
- CFTypeRef versionString = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleVersion"));
-
- if (versionString != 0 && CFGetTypeID (versionString) == CFStringGetTypeID())
- version = PlatformUtilities::cfStringToJuceString ((CFStringRef) versionString);
-
- CFTypeRef manuString = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleGetInfoString"));
-
- if (manuString != 0 && CFGetTypeID (manuString) == CFStringGetTypeID())
- manufacturer = PlatformUtilities::cfStringToJuceString ((CFStringRef) manuString);
-
- short resFileId = CFBundleOpenBundleResourceMap (bundleRef);
- UseResFile (resFileId);
-
- for (int i = 1; i <= Count1Resources ('thng'); ++i)
- {
- Handle h = Get1IndResource ('thng', i);
-
- if (h != 0)
- {
- HLock (h);
- const uint32* const types = (const uint32*) *h;
-
- if (types[0] == kAudioUnitType_MusicDevice
- || types[0] == kAudioUnitType_MusicEffect
- || types[0] == kAudioUnitType_Effect
- || types[0] == kAudioUnitType_Generator
- || types[0] == kAudioUnitType_Panner)
- {
- componentDesc.componentType = types[0];
- componentDesc.componentSubType = types[1];
- componentDesc.componentManufacturer = types[2];
- break;
- }
-
- HUnlock (h);
- ReleaseResource (h);
- }
- }
-
- CFBundleCloseBundleResourceMap (bundleRef, resFileId);
- CFRelease (bundleRef);
- }
- }
-
- return componentDesc.componentType != 0 && componentDesc.componentSubType != 0;
- }
-
- //==============================================================================
- void AudioUnitPluginInstance::initialise()
- {
- if (initialised || audioUnit == 0)
- return;
-
- log (T("Initialising AU: ") + pluginName);
-
- parameterIds.clear();
-
- {
- UInt32 paramListSize = 0;
- AudioUnitGetProperty (audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global,
- 0, 0, ¶mListSize);
-
- if (paramListSize > 0)
- {
- parameterIds.insertMultiple (0, 0, paramListSize / sizeof (int));
-
- AudioUnitGetProperty (audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global,
- 0, ¶meterIds.getReference(0), ¶mListSize);
- }
- }
-
- {
- AURenderCallbackStruct info;
- zerostruct (info);
- info.inputProcRefCon = this;
- info.inputProc = renderGetInputCallback;
-
- AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
- 0, &info, sizeof (info));
- }
-
- {
- HostCallbackInfo info;
- zerostruct (info);
- info.hostUserData = this;
- info.beatAndTempoProc = getBeatAndTempoCallback;
- info.musicalTimeLocationProc = getMusicalTimeLocationCallback;
- info.transportStateProc = getTransportStateCallback;
-
- AudioUnitSetProperty (audioUnit, kAudioUnitProperty_HostCallbacks, kAudioUnitScope_Global,
- 0, &info, sizeof (info));
- }
-
- int numIns, numOuts;
- getNumChannels (numIns, numOuts);
- setPlayConfigDetails (numIns, numOuts, 0, 0);
-
- initialised = AudioUnitInitialize (audioUnit) == noErr;
-
- setLatencySamples (0);
- }
-
-
- //==============================================================================
- void AudioUnitPluginInstance::prepareToPlay (double sampleRate_,
- int samplesPerBlockExpected)
- {
- initialise();
-
- if (initialised)
- {
- int numIns, numOuts;
- getNumChannels (numIns, numOuts);
-
- setPlayConfigDetails (numIns, numOuts, sampleRate_, samplesPerBlockExpected);
-
- Float64 latencySecs = 0.0;
- UInt32 latencySize = sizeof (latencySecs);
- AudioUnitGetProperty (audioUnit, kAudioUnitProperty_Latency, kAudioUnitScope_Global,
- 0, &latencySecs, &latencySize);
-
- setLatencySamples (roundDoubleToInt (latencySecs * sampleRate_));
-
- AudioUnitReset (audioUnit, kAudioUnitScope_Input, 0);
- AudioUnitReset (audioUnit, kAudioUnitScope_Output, 0);
- AudioUnitReset (audioUnit, kAudioUnitScope_Global, 0);
-
- AudioStreamBasicDescription stream;
- zerostruct (stream);
- stream.mSampleRate = sampleRate_;
- stream.mFormatID = kAudioFormatLinearPCM;
- stream.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
- stream.mFramesPerPacket = 1;
- stream.mBytesPerPacket = 4;
- stream.mBytesPerFrame = 4;
- stream.mBitsPerChannel = 32;
- stream.mChannelsPerFrame = numIns;
-
- OSStatus err = AudioUnitSetProperty (audioUnit,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Input,
- 0, &stream, sizeof (stream));
-
- stream.mChannelsPerFrame = numOuts;
-
- err = AudioUnitSetProperty (audioUnit,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Output,
- 0, &stream, sizeof (stream));
-
- juce_free (outputBufferList);
- outputBufferList = (AudioBufferList*) juce_calloc (sizeof (AudioBufferList) + sizeof (AudioBuffer) * (numOuts + 1));
- outputBufferList->mNumberBuffers = numOuts;
-
- for (int i = numOuts; --i >= 0;)
- outputBufferList->mBuffers[i].mNumberChannels = 1;
-
- zerostruct (timeStamp);
- timeStamp.mSampleTime = 0;
- timeStamp.mHostTime = AudioGetCurrentHostTime();
- timeStamp.mFlags = kAudioTimeStampSampleTimeValid | kAudioTimeStampHostTimeValid;
-
- currentBuffer = 0;
- wasPlaying = false;
- }
- }
-
- void AudioUnitPluginInstance::releaseResources()
- {
- if (initialised)
- {
- AudioUnitReset (audioUnit, kAudioUnitScope_Input, 0);
- AudioUnitReset (audioUnit, kAudioUnitScope_Output, 0);
- AudioUnitReset (audioUnit, kAudioUnitScope_Global, 0);
-
- juce_free (outputBufferList);
- outputBufferList = 0;
- currentBuffer = 0;
- }
- }
-
- OSStatus AudioUnitPluginInstance::renderGetInput (AudioUnitRenderActionFlags* ioActionFlags,
- const AudioTimeStamp* inTimeStamp,
- UInt32 inBusNumber,
- UInt32 inNumberFrames,
- AudioBufferList* ioData) const
- {
- if (inBusNumber == 0
- && currentBuffer != 0)
- {
- jassert (inNumberFrames == currentBuffer->getNumSamples()); // if this ever happens, might need to add extra handling
-
- for (int i = 0; i < ioData->mNumberBuffers; ++i)
- {
- if (i < currentBuffer->getNumChannels())
- {
- memcpy (ioData->mBuffers[i].mData,
- currentBuffer->getSampleData (i, 0),
- sizeof (float) * inNumberFrames);
- }
- else
- {
- zeromem (ioData->mBuffers[i].mData, sizeof (float) * inNumberFrames);
- }
- }
- }
-
- return noErr;
- }
-
- void AudioUnitPluginInstance::processBlock (AudioSampleBuffer& buffer,
- MidiBuffer& midiMessages)
- {
- const int numSamples = buffer.getNumSamples();
-
- if (initialised)
- {
- AudioUnitRenderActionFlags flags = 0;
-
- timeStamp.mHostTime = AudioGetCurrentHostTime();
-
- for (int i = getNumOutputChannels(); --i >= 0;)
- {
- outputBufferList->mBuffers[i].mDataByteSize = sizeof (float) * numSamples;
- outputBufferList->mBuffers[i].mData = buffer.getSampleData (i, 0);
- }
-
- currentBuffer = &buffer;
-
- if (wantsMidiMessages)
- {
- const uint8* midiEventData;
- int midiEventSize, midiEventPosition;
- MidiBuffer::Iterator i (midiMessages);
-
- while (i.getNextEvent (midiEventData, midiEventSize, midiEventPosition))
- {
- if (midiEventSize <= 3)
- MusicDeviceMIDIEvent (audioUnit,
- midiEventData[0], midiEventData[1], midiEventData[2],
- midiEventPosition);
- else
- MusicDeviceSysEx (audioUnit, midiEventData, midiEventSize);
- }
-
- midiMessages.clear();
- }
-
- AudioUnitRender (audioUnit, &flags, &timeStamp,
- 0, numSamples, outputBufferList);
-
- timeStamp.mSampleTime += numSamples;
- }
- else
- {
- // Not initialised, so just bypass..
- for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
- buffer.clear (i, 0, buffer.getNumSamples());
- }
- }
-
- //==============================================================================
- OSStatus AudioUnitPluginInstance::getBeatAndTempo (Float64* outCurrentBeat, Float64* outCurrentTempo) const
- {
- AudioPlayHead* const ph = getPlayHead();
- AudioPlayHead::CurrentPositionInfo result;
-
- if (ph != 0 && ph->getCurrentPosition (result))
- {
- *outCurrentBeat = result.ppqPosition;
- *outCurrentTempo = result.bpm;
- }
- else
- {
- *outCurrentBeat = 0;
- *outCurrentTempo = 120.0;
- }
-
- return noErr;
- }
-
- OSStatus AudioUnitPluginInstance::getMusicalTimeLocation (UInt32* outDeltaSampleOffsetToNextBeat,
- Float32* outTimeSig_Numerator,
- UInt32* outTimeSig_Denominator,
- Float64* outCurrentMeasureDownBeat) const
- {
- AudioPlayHead* const ph = getPlayHead();
- AudioPlayHead::CurrentPositionInfo result;
-
- if (ph != 0 && ph->getCurrentPosition (result))
- {
- *outTimeSig_Numerator = result.timeSigNumerator;
- *outTimeSig_Denominator = result.timeSigDenominator;
-
- *outDeltaSampleOffsetToNextBeat = 0; //xxx
- *outCurrentMeasureDownBeat = result.ppqPositionOfLastBarStart; //xxx wrong
- }
- else
- {
- *outDeltaSampleOffsetToNextBeat = 0;
- *outTimeSig_Numerator = 4;
- *outTimeSig_Denominator = 4;
- *outCurrentMeasureDownBeat = 0;
- }
-
- return noErr;
- }
-
- OSStatus AudioUnitPluginInstance::getTransportState (Boolean* outIsPlaying,
- Boolean* outTransportStateChanged,
- Float64* outCurrentSampleInTimeLine,
- Boolean* outIsCycling,
- Float64* outCycleStartBeat,
- Float64* outCycleEndBeat)
- {
- AudioPlayHead* const ph = getPlayHead();
- AudioPlayHead::CurrentPositionInfo result;
-
- if (ph != 0 && ph->getCurrentPosition (result))
- {
- *outIsPlaying = result.isPlaying;
- *outTransportStateChanged = result.isPlaying != wasPlaying;
- wasPlaying = result.isPlaying;
- *outCurrentSampleInTimeLine = roundDoubleToInt (result.timeInSeconds * getSampleRate());
- *outIsCycling = false;
- *outCycleStartBeat = 0;
- *outCycleEndBeat = 0;
- }
- else
- {
- *outIsPlaying = false;
- *outTransportStateChanged = false;
- *outCurrentSampleInTimeLine = 0;
- *outIsCycling = false;
- *outCycleStartBeat = 0;
- *outCycleEndBeat = 0;
- }
-
- return noErr;
- }
-
-
- //==============================================================================
- static VoidArray activeWindows;
-
- //==============================================================================
- class AudioUnitPluginWindow : public AudioProcessorEditor,
- public Timer
- {
- public:
- //==============================================================================
- AudioUnitPluginWindow (AudioUnitPluginInstance& plugin_)
- : AudioProcessorEditor (&plugin_),
- plugin (plugin_),
- isOpen (false),
- pluginWantsKeys (false),
- wasShowing (false),
- recursiveResize (false),
- viewComponent (0),
- pluginViewRef (0)
- {
- movementWatcher = new CompMovementWatcher (this);
-
- activeWindows.add (this);
-
- setOpaque (true);
- setVisible (true);
- setSize (1, 1);
-
- ComponentDescription viewList [16];
- UInt32 viewListSize = sizeof (viewList);
- AudioUnitGetProperty (plugin.audioUnit, kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global,
- 0, &viewList, &viewListSize);
-
- componentRecord = FindNextComponent (0, &viewList[0]);
- }
-
- ~AudioUnitPluginWindow()
- {
- deleteAndZero (movementWatcher);
-
- closePluginWindow();
-
- activeWindows.removeValue (this);
- plugin.editorBeingDeleted (this);
- }
-
- bool isValid() const throw() { return componentRecord != 0; }
-
- //==============================================================================
- void componentMovedOrResized()
- {
- if (recursiveResize)
- return;
-
- Component* const topComp = getTopLevelComponent();
-
- if (topComp->getPeer() != 0)
- {
- int x = 0, y = 0;
- relativePositionToOtherComponent (topComp, x, y);
-
- recursiveResize = true;
-
- if (pluginViewRef != 0)
- {
- HIRect r;
- r.origin.x = (float) x;
- r.origin.y = (float) y;
- r.size.width = (float) getWidth();
- r.size.height = (float) getHeight();
- HIViewSetFrame (pluginViewRef, &r);
- }
-
- recursiveResize = false;
- }
- }
-
- void componentVisibilityChanged()
- {
- const bool isShowingNow = isShowing();
-
- if (wasShowing != isShowingNow)
- {
- wasShowing = isShowingNow;
-
- if (isShowingNow)
- openPluginWindow();
- else
- closePluginWindow();
- }
-
- componentMovedOrResized();
- }
-
- void componentPeerChanged()
- {
- closePluginWindow();
- openPluginWindow();
- }
-
- void timerCallback()
- {
- if (pluginViewRef != 0)
- {
- HIRect bounds;
- HIViewGetBounds (pluginViewRef, &bounds);
- const int w = jmax (32, (int) bounds.size.width);
- const int h = jmax (32, (int) bounds.size.height);
-
- if (w != getWidth() || h != getHeight())
- {
- setSize (w, h);
- startTimer (50);
- }
- else
- {
- startTimer (jlimit (50, 500, getTimerInterval() + 20));
- }
- }
- }
-
- //==============================================================================
- bool keyStateChanged()
- {
- return pluginWantsKeys;
- }
-
- bool keyPressed (const KeyPress&)
- {
- return pluginWantsKeys;
- }
-
- //==============================================================================
- void paint (Graphics& g)
- {
- if (isOpen)
- {
- ComponentPeer* const peer = getPeer();
-
- if (peer != 0)
- {
- peer->addMaskedRegion (getScreenX() - peer->getScreenX(),
- getScreenY() - peer->getScreenY(),
- getWidth(), getHeight());
- }
- }
- else
- {
- g.fillAll (Colours::black);
- }
- }
-
- //==============================================================================
- void broughtToFront()
- {
- activeWindows.removeValue (this);
- activeWindows.add (this);
- }
-
- //==============================================================================
- juce_UseDebuggingNewOperator
-
- private:
- AudioUnitPluginInstance& plugin;
- bool isOpen, wasShowing, recursiveResize;
- bool pluginWantsKeys;
-
- ComponentRecord* componentRecord;
- AudioUnitCarbonView viewComponent;
- HIViewRef pluginViewRef;
-
- //==============================================================================
- void openPluginWindow()
- {
- if (isOpen || getWindowHandle() == 0 || componentRecord == 0)
- return;
-
- log (T("Opening AU GUI: ") + plugin.getName());
- isOpen = true;
-
- pluginWantsKeys = true; //xxx any way to find this out? Does it matter?
-
- viewComponent = (AudioUnitCarbonView) OpenComponent (componentRecord);
-
- if (viewComponent != 0)
- {
- Float32Point pos = { getScreenX() - getTopLevelComponent()->getScreenX(),
- getScreenY() - getTopLevelComponent()->getScreenY() };
- Float32Point size = { 250, 200 };
-
- AudioUnitCarbonViewCreate (viewComponent,
- plugin.audioUnit,
- (WindowRef) getWindowHandle(),
- HIViewGetRoot ((WindowRef) getWindowHandle()),
- &pos, &size,
- (ControlRef*) &pluginViewRef);
- }
-
- timerCallback(); // to set our comp to the right size
- repaint();
- }
-
- //==============================================================================
- void closePluginWindow()
- {
- stopTimer();
-
- if (isOpen)
- {
- log (T("Closing AU GUI: ") + plugin.getName());
- isOpen = false;
-
- if (viewComponent != 0)
- CloseComponent (viewComponent);
-
- pluginViewRef = 0;
- }
- }
-
- //==============================================================================
- class CompMovementWatcher : public ComponentMovementWatcher
- {
- public:
- CompMovementWatcher (AudioUnitPluginWindow* const owner_)
- : ComponentMovementWatcher (owner_),
- owner (owner_)
- {
- }
-
- //==============================================================================
- void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
- {
- owner->componentMovedOrResized();
- }
-
- void componentPeerChanged()
- {
- owner->componentPeerChanged();
- }
-
- void componentVisibilityChanged (Component&)
- {
- owner->componentVisibilityChanged();
- }
-
- private:
- AudioUnitPluginWindow* const owner;
- };
-
- CompMovementWatcher* movementWatcher;
- };
-
- //==============================================================================
- AudioProcessorEditor* AudioUnitPluginInstance::createEditor()
- {
- AudioUnitPluginWindow* w = new AudioUnitPluginWindow (*this);
-
- if (! w->isValid())
- deleteAndZero (w);
-
- return w;
- }
-
-
- //==============================================================================
- const String AudioUnitPluginInstance::getCategory() const
- {
- const char* result = 0;
-
- switch (componentDesc.componentType)
- {
- case kAudioUnitType_Effect:
- case kAudioUnitType_MusicEffect:
- result = "Effect";
- break;
- case kAudioUnitType_MusicDevice:
- result = "Synth";
- break;
- case kAudioUnitType_Generator:
- result = "Generator";
- break;
- case kAudioUnitType_Panner:
- result = "Panner";
- break;
- default:
- break;
- }
-
- return result;
- }
-
- //==============================================================================
- int AudioUnitPluginInstance::getNumParameters()
- {
- return parameterIds.size();
- }
-
- float AudioUnitPluginInstance::getParameter (int index)
- {
- const ScopedLock sl (lock);
-
- Float32 value = 0.0f;
-
- if (audioUnit != 0 && ((unsigned int) index) < (unsigned int) parameterIds.size())
- {
- AudioUnitGetParameter (audioUnit,
- (UInt32) parameterIds.getUnchecked (index),
- kAudioUnitScope_Global, 0,
- &value);
- }
-
- return value;
- }
-
- void AudioUnitPluginInstance::setParameter (int index, float newValue)
- {
- const ScopedLock sl (lock);
-
- if (audioUnit != 0 && ((unsigned int) index) < (unsigned int) parameterIds.size())
- {
- AudioUnitSetParameter (audioUnit,
- (UInt32) parameterIds.getUnchecked (index),
- kAudioUnitScope_Global, 0,
- newValue, 0);
- }
- }
-
- const String AudioUnitPluginInstance::getParameterName (int index)
- {
- AudioUnitParameterInfo info;
- zerostruct (info);
- UInt32 sz = sizeof (info);
-
- String name;
-
- if (AudioUnitGetProperty (audioUnit,
- kAudioUnitProperty_ParameterInfo,
- kAudioUnitScope_Global,
- parameterIds [index], &info, &sz) == noErr)
- {
- if ((info.flags & kAudioUnitParameterFlag_HasCFNameString) != 0)
- name = PlatformUtilities::cfStringToJuceString (info.cfNameString);
- else
- name = String (info.name, sizeof (info.name));
- }
-
- return name;
- }
-
- const String AudioUnitPluginInstance::getParameterText (int index)
- {
- return String (getParameter (index));
- }
-
- bool AudioUnitPluginInstance::isParameterAutomatable (int index) const
- {
- AudioUnitParameterInfo info;
- UInt32 sz = sizeof (info);
-
- if (AudioUnitGetProperty (audioUnit,
- kAudioUnitProperty_ParameterInfo,
- kAudioUnitScope_Global,
- parameterIds [index], &info, &sz) == noErr)
- {
- return (info.flags & kAudioUnitParameterFlag_NonRealTime) == 0;
- }
-
- return true;
- }
-
- //==============================================================================
- int AudioUnitPluginInstance::getNumPrograms()
- {
- CFArrayRef presets;
- UInt32 sz = sizeof (CFArrayRef);
- int num = 0;
-
- if (AudioUnitGetProperty (audioUnit,
- kAudioUnitProperty_FactoryPresets,
- kAudioUnitScope_Global,
- 0, &presets, &sz) == noErr)
- {
- num = (int) CFArrayGetCount (presets);
- CFRelease (presets);
- }
-
- return num;
- }
-
- int AudioUnitPluginInstance::getCurrentProgram()
- {
- AUPreset current;
- current.presetNumber = 0;
- UInt32 sz = sizeof (AUPreset);
-
- AudioUnitGetProperty (audioUnit,
- kAudioUnitProperty_FactoryPresets,
- kAudioUnitScope_Global,
- 0, ¤t, &sz);
-
- return current.presetNumber;
- }
-
- void AudioUnitPluginInstance::setCurrentProgram (int newIndex)
- {
- AUPreset current;
- current.presetNumber = newIndex;
- current.presetName = 0;
-
- AudioUnitSetProperty (audioUnit,
- kAudioUnitProperty_FactoryPresets,
- kAudioUnitScope_Global,
- 0, ¤t, sizeof (AUPreset));
- }
-
- const String AudioUnitPluginInstance::getProgramName (int index)
- {
- String s;
- CFArrayRef presets;
- UInt32 sz = sizeof (CFArrayRef);
-
- if (AudioUnitGetProperty (audioUnit,
- kAudioUnitProperty_FactoryPresets,
- kAudioUnitScope_Global,
- 0, &presets, &sz) == noErr)
- {
- for (CFIndex i = 0; i < CFArrayGetCount (presets); ++i)
- {
- const AUPreset* p = (const AUPreset*) CFArrayGetValueAtIndex (presets, i);
-
- if (p != 0 && p->presetNumber == index)
- {
- s = PlatformUtilities::cfStringToJuceString (p->presetName);
- break;
- }
- }
-
- CFRelease (presets);
- }
-
- return s;
- }
-
- void AudioUnitPluginInstance::changeProgramName (int index, const String& newName)
- {
- jassertfalse // xxx not implemented!
- }
-
- //==============================================================================
- const String AudioUnitPluginInstance::getInputChannelName (const int index) const
- {
- if (((unsigned int) index) < (unsigned int) getNumInputChannels())
- return T("Input ") + String (index + 1);
-
- return String::empty;
- }
-
- bool AudioUnitPluginInstance::isInputChannelStereoPair (int index) const
- {
- if (((unsigned int) index) >= (unsigned int) getNumInputChannels())
- return false;
-
-
- return true;
- }
-
- const String AudioUnitPluginInstance::getOutputChannelName (const int index) const
- {
- if (((unsigned int) index) < (unsigned int) getNumOutputChannels())
- return T("Output ") + String (index + 1);
-
- return String::empty;
- }
-
- bool AudioUnitPluginInstance::isOutputChannelStereoPair (int index) const
- {
- if (((unsigned int) index) >= (unsigned int) getNumOutputChannels())
- return false;
-
- return true;
- }
-
- //==============================================================================
- void AudioUnitPluginInstance::getStateInformation (MemoryBlock& destData)
- {
- getCurrentProgramStateInformation (destData);
- }
-
- void AudioUnitPluginInstance::getCurrentProgramStateInformation (MemoryBlock& destData)
- {
- CFPropertyListRef propertyList = 0;
- UInt32 sz = sizeof (CFPropertyListRef);
-
- if (AudioUnitGetProperty (audioUnit,
- kAudioUnitProperty_ClassInfo,
- kAudioUnitScope_Global,
- 0, &propertyList, &sz) == noErr)
- {
- CFWriteStreamRef stream = CFWriteStreamCreateWithAllocatedBuffers (kCFAllocatorDefault, kCFAllocatorDefault);
- CFWriteStreamOpen (stream);
-
- CFIndex bytesWritten = CFPropertyListWriteToStream (propertyList, stream, kCFPropertyListBinaryFormat_v1_0, 0);
- CFWriteStreamClose (stream);
-
- CFDataRef data = (CFDataRef) CFWriteStreamCopyProperty (stream, kCFStreamPropertyDataWritten);
-
- destData.setSize (bytesWritten);
- destData.copyFrom (CFDataGetBytePtr (data), 0, destData.getSize());
- CFRelease (data);
-
- CFRelease (stream);
- CFRelease (propertyList);
- }
- }
-
- void AudioUnitPluginInstance::setStateInformation (const void* data, int sizeInBytes)
- {
- setCurrentProgramStateInformation (data, sizeInBytes);
- }
-
- void AudioUnitPluginInstance::setCurrentProgramStateInformation (const void* data, int sizeInBytes)
- {
- CFReadStreamRef stream = CFReadStreamCreateWithBytesNoCopy (kCFAllocatorDefault,
- (const UInt8*) data,
- sizeInBytes,
- kCFAllocatorNull);
- CFReadStreamOpen (stream);
-
- CFPropertyListFormat format = kCFPropertyListBinaryFormat_v1_0;
- CFPropertyListRef propertyList = CFPropertyListCreateFromStream (kCFAllocatorDefault,
- stream,
- 0,
- kCFPropertyListImmutable,
- &format,
- 0);
- CFRelease (stream);
-
- if (propertyList != 0)
- AudioUnitSetProperty (audioUnit,
- kAudioUnitProperty_ClassInfo,
- kAudioUnitScope_Global,
- 0, &propertyList, sizeof (propertyList));
- }
-
- //==============================================================================
- //==============================================================================
- AudioUnitPluginFormat::AudioUnitPluginFormat()
- {
- }
-
- AudioUnitPluginFormat::~AudioUnitPluginFormat()
- {
- }
-
- void AudioUnitPluginFormat::findAllTypesForFile (OwnedArray <PluginDescription>& results,
- const File& file)
- {
- if (! fileMightContainThisPluginType (file))
- return;
-
- PluginDescription desc;
- desc.file = file;
- desc.uid = 0;
-
- AudioUnitPluginInstance* instance = dynamic_cast <AudioUnitPluginInstance*> (createInstanceFromDescription (desc));
-
- if (instance == 0)
- return;
-
- try
- {
- desc.fillInFromInstance (*instance);
-
- results.add (new PluginDescription (desc));
- }
- catch (...)
- {
- // crashed while loading...
- }
-
- deleteAndZero (instance);
- }
-
- AudioPluginInstance* AudioUnitPluginFormat::createInstanceFromDescription (const PluginDescription& desc)
- {
- AudioUnitPluginInstance* result = 0;
-
- if (fileMightContainThisPluginType (desc.file))
- {
- result = new AudioUnitPluginInstance (desc.file);
-
- if (result->audioUnit != 0)
- {
- result->initialise();
- }
- else
- {
- deleteAndZero (result);
- }
- }
-
- return result;
- }
-
- bool AudioUnitPluginFormat::fileMightContainThisPluginType (const File& f)
- {
- return f.hasFileExtension (T(".component"))
- && f.isDirectory();
- }
-
- const FileSearchPath AudioUnitPluginFormat::getDefaultLocationsToSearch()
- {
- return FileSearchPath ("~/Library/Audio/Plug-Ins/Components;/Library/Audio/Plug-Ins/Components");
- }
-
- #endif
- #endif
|