diff --git a/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm b/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm index fa20d7fc0a..24717b3cda 100644 --- a/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm +++ b/extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm @@ -1139,13 +1139,12 @@ public: class JuceAUView : public AUCarbonViewBase { AudioProcessor* juceFilter; - Component* windowComp; + ScopedPointer windowComp; public: JuceAUView (AudioUnitCarbonView auview) : AUCarbonViewBase (auview), - juceFilter (0), - windowComp (0) + juceFilter (0) { } @@ -1206,7 +1205,7 @@ private: if (windowComp != 0 && windowComp->getChildComponent(0) != 0) juceFilter->editorBeingDeleted ((AudioProcessorEditor*) windowComp->getChildComponent(0)); - deleteAndZero (windowComp); + windowComp = 0; } } diff --git a/extras/audio plugins/wrapper/RTAS/juce_RTAS_Wrapper.cpp b/extras/audio plugins/wrapper/RTAS/juce_RTAS_Wrapper.cpp index 0a1aad13e5..fddf821476 100644 --- a/extras/audio plugins/wrapper/RTAS/juce_RTAS_Wrapper.cpp +++ b/extras/audio plugins/wrapper/RTAS/juce_RTAS_Wrapper.cpp @@ -157,9 +157,7 @@ class JucePlugInProcess : public CEffectProcessMIDI, public: //============================================================================== JucePlugInProcess() - : midiBufferNode (0), - midiTransport (0), - prepared (false), + : prepared (false), sampleRate (44100.0) { juceFilter = createPluginFilter(); @@ -175,8 +173,8 @@ public: if (mLoggedIn) MIDILogOut(); - deleteAndZero (midiBufferNode); - deleteAndZero (midiTransport); + midiBufferNode = 0; + midiTransport = 0; if (prepared) juceFilter->releaseResources(); @@ -204,9 +202,7 @@ public: JuceCustomUIView (AudioProcessor* const filter_, JucePlugInProcess* const process_) : filter (filter_), - process (process_), - wrapper (0), - editorComp (0) + process (process_) { // setting the size in here crashes PT for some reason, so keep it simple.. } @@ -262,8 +258,7 @@ public: #else void* const hostWindow = (void*) GetWindowFromPort (port); #endif - deleteAndZero (wrapper); - + wrapper = 0; wrapper = new EditorCompWrapper (hostWindow, editorComp, this); process->touchAllParameters(); @@ -296,8 +291,8 @@ public: private: AudioProcessor* const filter; JucePlugInProcess* const process; - JUCE_NAMESPACE::Component* wrapper; - AudioProcessorEditor* editorComp; + ScopedPointer wrapper; + ScopedPointer editorComp; void deleteEditorComp() { @@ -314,8 +309,8 @@ public: filter->editorBeingDeleted (editorComp); - deleteAndZero (editorComp); - deleteAndZero (wrapper); + editorComp = 0; + wrapper = 0; } } @@ -550,22 +545,25 @@ protected: const Cmn_UInt32 bufferSize = mRTGlobals->mHWBufferSizeInSamples; - if (midiBufferNode->GetAdvanceScheduleTime() != bufferSize) - midiBufferNode->SetAdvanceScheduleTime (bufferSize); - - if (midiBufferNode->FillMIDIBuffer (mRTGlobals->mRunningTime, numSamples) == noErr) + if (midiBufferNode != 0) { - jassert (midiBufferNode->GetBufferPtr() != 0); - const int numMidiEvents = midiBufferNode->GetBufferSize(); + if (midiBufferNode->GetAdvanceScheduleTime() != bufferSize) + midiBufferNode->SetAdvanceScheduleTime (bufferSize); - for (int i = 0; i < numMidiEvents; ++i) + if (midiBufferNode->FillMIDIBuffer (mRTGlobals->mRunningTime, numSamples) == noErr) { - const DirectMidiPacket& m = midiBuffer[i]; + jassert (midiBufferNode->GetBufferPtr() != 0); + const int numMidiEvents = midiBufferNode->GetBufferSize(); - jassert ((int) m.mTimestamp < numSamples); + for (int i = 0; i < numMidiEvents; ++i) + { + const DirectMidiPacket& m = midiBuffer[i]; - midiEvents.addEvent (m.mData, m.mLength, - jlimit (0, (int) numSamples - 1, (int) m.mTimestamp)); + jassert ((int) m.mTimestamp < numSamples); + + midiEvents.addEvent (m.mData, m.mLength, + jlimit (0, (int) numSamples - 1, (int) m.mTimestamp)); + } } } #endif @@ -809,8 +807,8 @@ protected: private: AudioProcessor* juceFilter; MidiBuffer midiEvents; - CEffectMIDIOtherBufferedNode* midiBufferNode; - CEffectMIDITransport* midiTransport; + ScopedPointer midiBufferNode; + ScopedPointer midiTransport; DirectMidiPacket midiBuffer [midiBufferSize]; JUCE_NAMESPACE::MemoryBlock tempFilterData; diff --git a/extras/audio plugins/wrapper/Standalone/juce_StandaloneFilterWindow.cpp b/extras/audio plugins/wrapper/Standalone/juce_StandaloneFilterWindow.cpp index 8f5645ea66..1bb88dd8a9 100644 --- a/extras/audio plugins/wrapper/Standalone/juce_StandaloneFilterWindow.cpp +++ b/extras/audio plugins/wrapper/Standalone/juce_StandaloneFilterWindow.cpp @@ -39,16 +39,13 @@ StandaloneFilterWindow::StandaloneFilterWindow (const String& title, : DocumentWindow (title, backgroundColour, DocumentWindow::minimiseButton | DocumentWindow::closeButton), - filter (0), - deviceManager (0), - optionsButton (0) + optionsButton ("options") { setTitleBarButtonsRequired (DocumentWindow::minimiseButton | DocumentWindow::closeButton, false); - optionsButton = new TextButton ("options"); - Component::addAndMakeVisible (optionsButton); - optionsButton->addButtonListener (this); - optionsButton->setTriggeredOnMouseDown (true); + Component::addAndMakeVisible (&optionsButton); + optionsButton.addButtonListener (this); + optionsButton.setTriggeredOnMouseDown (true); JUCE_TRY { @@ -115,8 +112,6 @@ StandaloneFilterWindow::~StandaloneFilterWindow() globalSettings->setValue ("windowX", getX()); globalSettings->setValue ("windowY", getY()); - deleteAndZero (optionsButton); - if (globalSettings != 0 && deviceManager != 0) { XmlElement* const xml = deviceManager->createStateXml(); @@ -124,7 +119,7 @@ StandaloneFilterWindow::~StandaloneFilterWindow() delete xml; } - deleteAndZero (deviceManager); + deviceManager = 0; if (globalSettings != 0 && filter != 0) { @@ -149,7 +144,7 @@ void StandaloneFilterWindow::deleteFilter() setContentComponent (0, true); } - deleteAndZero (filter); + filter = 0; } void StandaloneFilterWindow::resetFilter() @@ -258,8 +253,7 @@ void StandaloneFilterWindow::resized() { DocumentWindow::resized(); - if (optionsButton != 0) - optionsButton->setBounds (8, 6, 60, getTitleBarHeight() - 8); + optionsButton.setBounds (8, 6, 60, getTitleBarHeight() - 8); } void StandaloneFilterWindow::buttonClicked (Button*) @@ -275,7 +269,7 @@ void StandaloneFilterWindow::buttonClicked (Button*) m.addSeparator(); m.addItem (4, TRANS("Reset to default state")); - switch (m.showAt (optionsButton)) + switch (m.showAt (&optionsButton)) { case 1: showAudioSettingsDialog(); diff --git a/extras/audio plugins/wrapper/Standalone/juce_StandaloneFilterWindow.h b/extras/audio plugins/wrapper/Standalone/juce_StandaloneFilterWindow.h index 668f693490..81a491a264 100644 --- a/extras/audio plugins/wrapper/Standalone/juce_StandaloneFilterWindow.h +++ b/extras/audio plugins/wrapper/Standalone/juce_StandaloneFilterWindow.h @@ -77,9 +77,9 @@ public: juce_UseDebuggingNewOperator private: - AudioProcessor* filter; - AudioFilterStreamingDeviceManager* deviceManager; - Button* optionsButton; + ScopedPointer filter; + ScopedPointer deviceManager; + TextButton optionsButton; void deleteFilter(); diff --git a/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp b/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp index aca7b934c3..5fcc5a9f55 100644 --- a/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp +++ b/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp @@ -275,7 +275,6 @@ public: filter_->getNumParameters()), filter (filter_) { - editorComp = 0; chunkMemoryTime = 0; isProcessing = false; hasShutdown = false; @@ -1128,7 +1127,7 @@ public: filter->editorBeingDeleted (editorComp->getEditorComp()); - deleteAndZero (editorComp); + editorComp = 0; // there's some kind of component currently modal, but the host // is trying to delete our plugin. You should try to avoid this happening.. @@ -1420,7 +1419,7 @@ private: AudioProcessor* filter; JUCE_NAMESPACE::MemoryBlock chunkMemory; JUCE_NAMESPACE::uint32 chunkMemoryTime; - EditorCompWrapper* editorComp; + ScopedPointer editorComp; ERect editorSize; MidiBuffer midiEvents; VSTMidiEventList outgoingEvents; diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index cc7d369f25..61ec44dce7 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -7938,7 +7938,7 @@ DatagramSocket::~DatagramSocket() { close(); - delete ((struct sockaddr_in*) serverAddress); + delete static_cast (serverAddress); serverAddress = 0; } @@ -30774,10 +30774,9 @@ class AudioUnitPluginWindowCocoa : public AudioProcessorEditor public: AudioUnitPluginWindowCocoa (AudioUnitPluginInstance& plugin_, const bool createGenericViewIfNeeded) : AudioProcessorEditor (&plugin_), - plugin (plugin_), - wrapper (0) + plugin (plugin_) { - addAndMakeVisible (wrapper = new NSViewComponent()); + addAndMakeVisible (&wrapper); setOpaque (true); setVisible (true); @@ -30790,15 +30789,13 @@ public: { const bool wasValid = isValid(); - wrapper->setView (0); + wrapper.setView (0); if (wasValid) plugin.editorBeingDeleted (this); - - delete wrapper; } - bool isValid() const { return wrapper->getView() != 0; } + bool isValid() const { return wrapper.getView() != 0; } void paint (Graphics& g) { @@ -30807,12 +30804,12 @@ public: void resized() { - wrapper->setSize (getWidth(), getHeight()); + wrapper.setSize (getWidth(), getHeight()); } private: AudioUnitPluginInstance& plugin; - NSViewComponent* wrapper; + NSViewComponent wrapper; bool createView (const bool createGenericViewIfNeeded) { @@ -30858,7 +30855,7 @@ private: if (createGenericViewIfNeeded && (pluginView == 0)) pluginView = [[AUGenericView alloc] initWithAudioUnit: plugin.audioUnit]; - wrapper->setView (pluginView); + wrapper.setView (pluginView); if (pluginView != 0) setSize ([pluginView frame].size.width, @@ -57806,35 +57803,19 @@ FileChooserDialogBox::FileChooserDialogBox (const String& name, : ResizableWindow (name, backgroundColour, true), warnAboutOverwritingExistingFiles (warnAboutOverwritingExistingFiles_) { - content = new ContentComponent(); - content->setName (name); - content->instructions = instructions; - content->chooserComponent = &chooserComponent; - - content->addAndMakeVisible (&chooserComponent); - - content->okButton = new TextButton (chooserComponent.getActionVerb()); - content->addAndMakeVisible (content->okButton); - content->okButton->addButtonListener (this); - content->okButton->setEnabled (chooserComponent.currentFileIsValid()); - content->okButton->addShortcut (KeyPress (KeyPress::returnKey, 0, 0)); - - content->cancelButton = new TextButton (TRANS("Cancel")); - content->addAndMakeVisible (content->cancelButton); - content->cancelButton->addButtonListener (this); - content->cancelButton->addShortcut (KeyPress (KeyPress::escapeKey, 0, 0)); - - setContentComponent (content); + setContentComponent (content = new ContentComponent (name, instructions, chooserComponent)); setResizable (true, true); setResizeLimits (300, 300, 1200, 1000); - content->chooserComponent->addListener (this); + content->okButton.addButtonListener (this); + content->cancelButton.addButtonListener (this); + content->chooserComponent.addListener (this); } FileChooserDialogBox::~FileChooserDialogBox() { - content->chooserComponent->removeListener (this); + content->chooserComponent.removeListener (this); } bool FileChooserDialogBox::show (int w, int h) @@ -57846,7 +57827,7 @@ bool FileChooserDialogBox::showAt (int x, int y, int w, int h) { if (w <= 0) { - Component* const previewComp = content->chooserComponent->getPreviewComponent(); + Component* const previewComp = content->chooserComponent.getPreviewComponent(); if (previewComp != 0) w = 400 + previewComp->getWidth(); else @@ -57868,16 +57849,16 @@ bool FileChooserDialogBox::showAt (int x, int y, int w, int h) void FileChooserDialogBox::buttonClicked (Button* button) { - if (button == content->okButton) + if (button == &(content->okButton)) { if (warnAboutOverwritingExistingFiles - && content->chooserComponent->isSaveMode() - && content->chooserComponent->getSelectedFile(0).exists()) + && content->chooserComponent.isSaveMode() + && content->chooserComponent.getSelectedFile(0).exists()) { if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, TRANS("File already exists"), TRANS("There's already a file called:") - + "\n\n" + content->chooserComponent->getSelectedFile(0).getFullPathName() + + "\n\n" + content->chooserComponent.getSelectedFile(0).getFullPathName() + "\n\n" + TRANS("Are you sure you want to overwrite it?"), TRANS("overwrite"), TRANS("cancel"))) @@ -57888,8 +57869,10 @@ void FileChooserDialogBox::buttonClicked (Button* button) exitModalState (1); } - else if (button == content->cancelButton) + else if (button == &(content->cancelButton)) + { closeButtonPressed(); + } } void FileChooserDialogBox::closeButtonPressed() @@ -57899,7 +57882,7 @@ void FileChooserDialogBox::closeButtonPressed() void FileChooserDialogBox::selectionChanged() { - content->okButton->setEnabled (content->chooserComponent->currentFileIsValid()); + content->okButton.setEnabled (content->chooserComponent.currentFileIsValid()); } void FileChooserDialogBox::fileClicked (const File&, const MouseEvent&) @@ -57909,18 +57892,29 @@ void FileChooserDialogBox::fileClicked (const File&, const MouseEvent&) void FileChooserDialogBox::fileDoubleClicked (const File&) { selectionChanged(); - content->okButton->triggerClick(); + content->okButton.triggerClick(); } -FileChooserDialogBox::ContentComponent::ContentComponent() +FileChooserDialogBox::ContentComponent::ContentComponent (const String& name, const String& instructions_, FileBrowserComponent& chooserComponent_) + : Component (name), instructions (instructions_), + chooserComponent (chooserComponent_), + okButton (chooserComponent_.getActionVerb()), + cancelButton (TRANS ("Cancel")) { + addAndMakeVisible (&chooserComponent); + + addAndMakeVisible (&okButton); + okButton.setEnabled (chooserComponent.currentFileIsValid()); + okButton.addShortcut (KeyPress (KeyPress::returnKey, 0, 0)); + + addAndMakeVisible (&cancelButton); + cancelButton.addShortcut (KeyPress (KeyPress::escapeKey, 0, 0)); + setInterceptsMouseClicks (false, true); } FileChooserDialogBox::ContentComponent::~ContentComponent() { - delete okButton; - delete cancelButton; } void FileChooserDialogBox::ContentComponent::paint (Graphics& g) @@ -57939,13 +57933,13 @@ void FileChooserDialogBox::ContentComponent::resized() const int buttonHeight = 26; const int buttonY = getHeight() - buttonHeight - 8; - chooserComponent->setBounds (0, y, getWidth(), buttonY - y - 20); + chooserComponent.setBounds (0, y, getWidth(), buttonY - y - 20); - okButton->setBounds (proportionOfWidth (0.25f), buttonY, - proportionOfWidth (0.2f), buttonHeight); + okButton.setBounds (proportionOfWidth (0.25f), buttonY, + proportionOfWidth (0.2f), buttonHeight); - cancelButton->setBounds (proportionOfWidth (0.55f), buttonY, - proportionOfWidth (0.2f), buttonHeight); + cancelButton.setBounds (proportionOfWidth (0.55f), buttonY, + proportionOfWidth (0.2f), buttonHeight); } END_JUCE_NAMESPACE @@ -61133,7 +61127,6 @@ public: MultiDocumentPanel::MultiDocumentPanel() : mode (MaximisedWindowsWithTabs), - tabComponent (0), backgroundColour (Colours::lightblue), maximumNumDocuments (0), numDocsBeforeTabsUsed (0) @@ -61326,7 +61319,7 @@ bool MultiDocumentPanel::closeDocument (Component* component, delete component; if (tabComponent != 0 && tabComponent->getNumTabs() <= numDocsBeforeTabsUsed) - deleteAndZero (tabComponent); + tabComponent = 0; components.removeValue (component); @@ -61426,7 +61419,7 @@ void MultiDocumentPanel::setLayoutMode (const LayoutMode newLayoutMode) if (mode == FloatingWindows) { - deleteAndZero (tabComponent); + tabComponent = 0; } else { @@ -77667,8 +77660,7 @@ ResizableWindow::~ResizableWindow() { resizableCorner = 0; resizableBorder = 0; - delete static_cast (contentComponent); - contentComponent = 0; + contentComponent.deleteAndZero(); // have you been adding your own components directly to this window..? tut tut tut. // Read the instructions for using a ResizableWindow! @@ -77694,8 +77686,8 @@ void ResizableWindow::setContentComponent (Component* const newContentComponent, if (newContentComponent != static_cast (contentComponent)) { if (deleteOldOne) - delete static_cast (contentComponent); // (avoid using a scoped pointer for this, so that it survives - // external deletion of the content comp) + contentComponent.deleteAndZero(); // (avoid using a scoped pointer for this, so that it survives + // external deletion of the content comp) else removeChildComponent (contentComponent); @@ -87984,12 +87976,12 @@ private: Path path; Drawable* s = parseShape (*e, path); - delete s; + delete s; // xxx not finished! } else if (e->hasTagName ("tspan")) { Drawable* s = parseText (*e); - delete s; + delete s; // xxx not finished! } } @@ -239638,7 +239630,6 @@ public: isMouseOver (false), hasCreatedCaret (false), currentWindowIcon (0), - taskBarIcon (0), dropTarget (0) { callFunctionIfNotLocked (&createWindowCallback, this); @@ -239653,16 +239644,12 @@ public: if (shadower != 0) shadower->setOwner (component); } - else - { - shadower = 0; - } } ~Win32ComponentPeer() { setTaskBarIcon (Image()); - deleteAndZero (shadower); + shadower = 0; // do this before the next bit to avoid messages arriving for this window // before it's destroyed @@ -240022,7 +240009,7 @@ public: taskBarIcon->uFlags = 0; Shell_NotifyIcon (NIM_DELETE, taskBarIcon); DestroyIcon (taskBarIcon->hIcon); - deleteAndZero (taskBarIcon); + taskBarIcon = 0; } } @@ -240087,11 +240074,11 @@ public: private: HWND hwnd; - DropShadower* shadower; + ScopedPointer shadower; bool fullScreen, isDragging, isMouseOver, hasCreatedCaret; BorderSize windowBorder; HICON currentWindowIcon; - NOTIFYICONDATA* taskBarIcon; + ScopedPointer taskBarIcon; IDropTarget* dropTarget; class TemporaryImage : public Timer @@ -244011,7 +243998,6 @@ public: HGLRC contextToShareWith, const OpenGLPixelFormat& pixelFormat) : renderContext (0), - nativeWindow (0), dc (0), component (component_) { @@ -244047,7 +244033,7 @@ public: { deleteContext(); ReleaseDC ((HWND) nativeWindow->getNativeHandle(), dc); - delete nativeWindow; + nativeWindow = 0; } void deleteContext() @@ -244200,7 +244186,7 @@ public: // old one and create a new one.. jassert (nativeWindow != 0); ReleaseDC ((HWND) nativeWindow->getNativeHandle(), dc); - delete nativeWindow; + nativeWindow = 0; createNativeWindow(); @@ -244314,7 +244300,7 @@ public: HGLRC renderContext; private: - Win32ComponentPeer* nativeWindow; + ScopedPointer nativeWindow; Component* const component; HDC dc; @@ -251418,9 +251404,7 @@ public: Thread ("Juce WASAPI"), isOpen_ (false), isStarted (false), - outputDevice (0), outputDeviceId (outputDeviceId_), - inputDevice (0), inputDeviceId (inputDeviceId_), useExclusiveMode (useExclusiveMode_), currentBufferSizeSamples (0), @@ -251432,9 +251416,6 @@ public: ~WASAPIAudioIODevice() { close(); - - deleteAndZero (inputDevice); - deleteAndZero (outputDevice); } bool initialise() @@ -251458,7 +251439,8 @@ public: } else { - WASAPIDeviceBase* const d = inputDevice != 0 ? (WASAPIDeviceBase*) inputDevice : (WASAPIDeviceBase*) outputDevice; + WASAPIDeviceBase* d = inputDevice != 0 ? static_cast (inputDevice) + : static_cast (outputDevice); defaultSampleRate = d->defaultSampleRate; minBufferSize = d->minBufferSize; defaultBufferSize = d->defaultBufferSize; @@ -251551,6 +251533,7 @@ public: if (inputDevice != 0) ResetEvent (inputDevice->clientEvent); + if (outputDevice != 0) ResetEvent (outputDevice->clientEvent); @@ -251722,8 +251705,8 @@ public: private: // Device stats... - WASAPIInputDevice* inputDevice; - WASAPIOutputDevice* outputDevice; + ScopedPointer inputDevice; + ScopedPointer outputDevice; const bool useExclusiveMode; double defaultSampleRate; int minBufferSize, defaultBufferSize; @@ -253747,9 +253730,9 @@ struct NamedPipeInternal void NamedPipe::cancelPendingReads() { - while (internal != 0 && ((NamedPipeInternal*) internal)->blocked) + while (internal != 0 && static_cast (internal)->blocked) { - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = static_cast (internal); intern->stopReadOperation = true; @@ -253767,7 +253750,7 @@ void NamedPipe::cancelPendingReads() void NamedPipe::close() { - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = static_cast (internal); if (intern != 0) { @@ -253827,7 +253810,7 @@ bool NamedPipe::openInternal (const String& pipeName, const bool createPipe) int NamedPipe::read (void* destBuffer, int maxBytesToRead, int /*timeOutMilliseconds*/) { int bytesRead = -1; - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = static_cast (internal); if (intern != 0) { @@ -253875,7 +253858,7 @@ int NamedPipe::read (void* destBuffer, int maxBytesToRead, int /*timeOutMillisec int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds) { int bytesWritten = -1; - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = static_cast (internal); if (intern != 0) { @@ -261104,8 +261087,7 @@ MidiOutput* MidiOutput::createNewDevice (const String& deviceName) MidiOutput::~MidiOutput() { - MidiOutputDevice* const device = (MidiOutputDevice*) internal; - delete device; + delete static_cast (internal); } void MidiOutput::reset() @@ -261123,7 +261105,7 @@ void MidiOutput::setVolume (float leftVol, float rightVol) void MidiOutput::sendMessageNow (const MidiMessage& message) { - ((MidiOutputDevice*) internal)->sendMessageNow (message); + static_cast (internal)->sendMessageNow (message); } class MidiInputThread : public Thread @@ -261215,18 +261197,17 @@ MidiInput::MidiInput (const String& name_) MidiInput::~MidiInput() { stop(); - MidiInputThread* const thread = (MidiInputThread*) internal; - delete thread; + delete static_cast (internal); } void MidiInput::start() { - ((MidiInputThread*) internal)->startThread(); + static_cast (internal)->startThread(); } void MidiInput::stop() { - ((MidiInputThread*) internal)->stopThread (3000); + static_cast (internal)->stopThread (3000); } int MidiInput::getDefaultDeviceIndex() @@ -262399,9 +262380,9 @@ struct NamedPipeInternal void NamedPipe::cancelPendingReads() { - while (internal != 0 && ((NamedPipeInternal*) internal)->blocked) + while (internal != 0 && static_cast (internal)->blocked) { - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = static_cast (internal); intern->stopReadOperation = true; @@ -262419,7 +262400,7 @@ void NamedPipe::cancelPendingReads() void NamedPipe::close() { - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = static_cast (internal); if (intern != 0) { @@ -262479,7 +262460,7 @@ bool NamedPipe::openInternal (const String& pipeName, const bool createPipe) int NamedPipe::read (void* destBuffer, int maxBytesToRead, int /*timeOutMilliseconds*/) { int bytesRead = -1; - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = static_cast (internal); if (intern != 0) { @@ -262527,7 +262508,7 @@ int NamedPipe::read (void* destBuffer, int maxBytesToRead, int /*timeOutMillisec int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds) { int bytesWritten = -1; - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = static_cast (internal); if (intern != 0) { @@ -268369,7 +268350,7 @@ MidiOutput* MidiOutput::createNewDevice (const String& deviceName) MidiOutput::~MidiOutput() { - delete (MidiPortAndEndpoint*) internal; + delete static_cast (internal); } void MidiOutput::reset() @@ -268387,7 +268368,7 @@ void MidiOutput::setVolume (float /*leftVol*/, float /*rightVol*/) void MidiOutput::sendMessageNow (const MidiMessage& message) { - MidiPortAndEndpoint* const mpe = (MidiPortAndEndpoint*) internal; + MidiPortAndEndpoint* const mpe = static_cast (internal); if (message.isSysEx()) { @@ -268678,7 +268659,7 @@ MidiInput::MidiInput (const String& name_) MidiInput::~MidiInput() { - MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; + MidiPortAndCallback* const mpc = static_cast (internal); mpc->active = false; { @@ -268696,13 +268677,13 @@ MidiInput::~MidiInput() void MidiInput::start() { const ScopedLock sl (CoreMidiCallbacks::callbackLock); - ((MidiPortAndCallback*) internal)->active = true; + static_cast (internal)->active = true; } void MidiInput::stop() { const ScopedLock sl (CoreMidiCallbacks::callbackLock); - ((MidiPortAndCallback*) internal)->active = false; + static_cast (internal)->active = false; } #undef log @@ -276825,7 +276806,7 @@ MidiOutput* MidiOutput::createNewDevice (const String& deviceName) MidiOutput::~MidiOutput() { - delete (MidiPortAndEndpoint*) internal; + delete static_cast (internal); } void MidiOutput::reset() @@ -276843,7 +276824,7 @@ void MidiOutput::setVolume (float /*leftVol*/, float /*rightVol*/) void MidiOutput::sendMessageNow (const MidiMessage& message) { - MidiPortAndEndpoint* const mpe = (MidiPortAndEndpoint*) internal; + MidiPortAndEndpoint* const mpe = static_cast (internal); if (message.isSysEx()) { @@ -277134,7 +277115,7 @@ MidiInput::MidiInput (const String& name_) MidiInput::~MidiInput() { - MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; + MidiPortAndCallback* const mpc = static_cast (internal); mpc->active = false; { @@ -277152,13 +277133,13 @@ MidiInput::~MidiInput() void MidiInput::start() { const ScopedLock sl (CoreMidiCallbacks::callbackLock); - ((MidiPortAndCallback*) internal)->active = true; + static_cast (internal)->active = true; } void MidiInput::stop() { const ScopedLock sl (CoreMidiCallbacks::callbackLock); - ((MidiPortAndCallback*) internal)->active = false; + static_cast (internal)->active = false; } #undef log diff --git a/juce_amalgamated.h b/juce_amalgamated.h index e934eafd03..ce723e7ca2 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -27298,6 +27298,9 @@ public: /** Returns the component that this pointer refers to, or null if the component no longer exists. */ const ComponentType* operator->() const throw() { jassert (comp != 0); return comp; } + /** If the component is valid, this deletes it and sets this pointer to null. */ + void deleteAndZero() { delete comp; jassert (comp == 0); } + juce_UseDebuggingNewOperator private: @@ -50521,7 +50524,7 @@ private: class ContentComponent : public Component { public: - ContentComponent(); + ContentComponent (const String& name, const String& instructions, FileBrowserComponent& chooserComponent); ~ContentComponent(); void paint (Graphics& g); @@ -50530,10 +50533,8 @@ private: String instructions; GlyphArrangement text; - FileBrowserComponent* chooserComponent; - FilePreviewComponent* previewComponent; - TextButton* okButton; - TextButton* cancelButton; + FileBrowserComponent& chooserComponent; + TextButton okButton, cancelButton; }; ContentComponent* content; @@ -52830,7 +52831,7 @@ public: private: LayoutMode mode; Array components; - TabbedComponent* tabComponent; + ScopedPointer tabComponent; Colour backgroundColour; int maximumNumDocuments, numDocsBeforeTabsUsed; diff --git a/src/audio/plugins/formats/juce_AudioUnitPluginFormat.mm b/src/audio/plugins/formats/juce_AudioUnitPluginFormat.mm index eb5c4373e8..c9af242ef8 100644 --- a/src/audio/plugins/formats/juce_AudioUnitPluginFormat.mm +++ b/src/audio/plugins/formats/juce_AudioUnitPluginFormat.mm @@ -1,1528 +1,1525 @@ -/* - ============================================================================== - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-10 by Raw Material Software Ltd. - - ------------------------------------------------------------------------------ - - JUCE can be redistributed and/or modified under the terms of the GNU General - Public License (Version 2), as published by the Free Software Foundation. - A copy of the license is included in the JUCE distribution, or can be found - online at www.gnu.org/licenses. - - 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. - - ------------------------------------------------------------------------------ - - To release a closed-source product which uses JUCE, commercial licenses are - available: visit www.rawmaterialsoftware.com/juce for more information. - - ============================================================================== -*/ - -#include "../../../core/juce_TargetPlatform.h" -#include "../../../../juce_Config.h" - -#if JUCE_PLUGINHOST_AU && ! (JUCE_LINUX || JUCE_WINDOWS) - -#include -#include -#include - -#if JUCE_SUPPORT_CARBON -#include -#include -#endif - -#include "../../../core/juce_StandardHeader.h" - -BEGIN_JUCE_NAMESPACE - -#include "juce_AudioUnitPluginFormat.h" -#include "../juce_PluginDescription.h" -#include "../../../threads/juce_ScopedLock.h" -#include "../../../events/juce_Timer.h" -#include "../../../core/juce_PlatformUtilities.h" -#include "../../../gui/components/layout/juce_ComponentMovementWatcher.h" -#include "../../../gui/components/windows/juce_ComponentPeer.h" -#include "../../../gui/components/special/juce_NSViewComponent.h" -#if JUCE_MAC && JUCE_SUPPORT_CARBON -#include "../../../native/mac/juce_mac_CarbonViewWrapperComponent.h" -#endif - -#if JUCE_MAC - -// 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 - -namespace AudioUnitFormatHelpers -{ - static int insideCallback = 0; - - static const String osTypeToString (OSType type) - { - char s[4]; - s[0] = (char) (((uint32) type) >> 24); - s[1] = (char) (((uint32) type) >> 16); - s[2] = (char) (((uint32) type) >> 8); - s[3] = (char) ((uint32) type); - return String (s, 4); - } - - static OSType stringToOSType (const String& s1) - { - const String s (s1 + " "); - - return (((OSType) (unsigned char) s[0]) << 24) - | (((OSType) (unsigned char) s[1]) << 16) - | (((OSType) (unsigned char) s[2]) << 8) - | ((OSType) (unsigned char) s[3]); - } - - static const char* auIdentifierPrefix = "AudioUnit:"; - - static const String createAUPluginIdentifier (const ComponentDescription& desc) - { - jassert (osTypeToString ('abcd') == "abcd"); // agh, must have got the endianness wrong.. - jassert (stringToOSType ("abcd") == (OSType) 'abcd'); // ditto - - String s (auIdentifierPrefix); - - if (desc.componentType == kAudioUnitType_MusicDevice) - s << "Synths/"; - else if (desc.componentType == kAudioUnitType_MusicEffect - || desc.componentType == kAudioUnitType_Effect) - s << "Effects/"; - else if (desc.componentType == kAudioUnitType_Generator) - s << "Generators/"; - else if (desc.componentType == kAudioUnitType_Panner) - s << "Panners/"; - - s << osTypeToString (desc.componentType) << "," - << osTypeToString (desc.componentSubType) << "," - << osTypeToString (desc.componentManufacturer); - - return s; - } - - static void getAUDetails (ComponentRecord* comp, String& name, String& manufacturer) - { - Handle componentNameHandle = NewHandle (sizeof (void*)); - Handle componentInfoHandle = NewHandle (sizeof (void*)); - - if (componentNameHandle != 0 && componentInfoHandle != 0) - { - ComponentDescription desc; - - if (GetComponentInfo (comp, &desc, componentNameHandle, componentInfoHandle, 0) == noErr) - { - ConstStr255Param nameString = (ConstStr255Param) (*componentNameHandle); - ConstStr255Param infoString = (ConstStr255Param) (*componentInfoHandle); - - if (nameString != 0 && nameString[0] != 0) - { - const String all ((const char*) nameString + 1, nameString[0]); - DBG ("name: "+ all); - - manufacturer = all.upToFirstOccurrenceOf (":", false, false).trim(); - name = all.fromFirstOccurrenceOf (":", false, false).trim(); - } - - if (infoString != 0 && infoString[0] != 0) - { - DBG ("info: " + String ((const char*) infoString + 1, infoString[0])); - } - - if (name.isEmpty()) - name = ""; - } - - DisposeHandle (componentNameHandle); - DisposeHandle (componentInfoHandle); - } - } - - static bool getComponentDescFromIdentifier (const String& fileOrIdentifier, ComponentDescription& desc, - String& name, String& version, String& manufacturer) - { - zerostruct (desc); - - if (fileOrIdentifier.startsWithIgnoreCase (auIdentifierPrefix)) - { - String s (fileOrIdentifier.substring (jmax (fileOrIdentifier.lastIndexOfChar (':'), - fileOrIdentifier.lastIndexOfChar ('/')) + 1)); - - StringArray tokens; - tokens.addTokens (s, ",", String::empty); - tokens.trim(); - tokens.removeEmptyStrings(); - - if (tokens.size() == 3) - { - desc.componentType = stringToOSType (tokens[0]); - desc.componentSubType = stringToOSType (tokens[1]); - desc.componentManufacturer = stringToOSType (tokens[2]); - - ComponentRecord* comp = FindNextComponent (0, &desc); - - if (comp != 0) - { - getAUDetails (comp, name, manufacturer); - return true; - } - } - } - - return false; - } -} - -//============================================================================== -class AudioUnitPluginWindowCarbon; -class AudioUnitPluginWindowCocoa; - -//============================================================================== -class AudioUnitPluginInstance : public AudioPluginInstance -{ -public: - //============================================================================== - ~AudioUnitPluginInstance(); - - //============================================================================== - // AudioPluginInstance methods: - - void fillInPluginDescription (PluginDescription& desc) const - { - desc.name = pluginName; - desc.fileOrIdentifier = AudioUnitFormatHelpers::createAUPluginIdentifier (componentDesc); - desc.uid = ((int) componentDesc.componentType) - ^ ((int) componentDesc.componentSubType) - ^ ((int) componentDesc.componentManufacturer); - desc.lastFileModTime = 0; - desc.pluginFormatName = "AudioUnit"; - desc.category = getCategory(); - desc.manufacturerName = manufacturer; - desc.version = version; - desc.numInputChannels = getNumInputChannels(); - desc.numOutputChannels = getNumOutputChannels(); - desc.isInstrument = (componentDesc.componentType == kAudioUnitType_MusicDevice); - } - - const String getName() const { return pluginName; } - 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 AudioUnitPluginWindowCarbon; - friend class AudioUnitPluginWindowCocoa; - friend class AudioUnitPluginFormat; - - ComponentDescription componentDesc; - String pluginName, manufacturer, version; - String fileOrIdentifier; - CriticalSection lock; - bool initialised, wantsMidiMessages, wasPlaying; - - HeapBlock outputBufferList; - AudioTimeStamp timeStamp; - AudioSampleBuffer* currentBuffer; - - AudioUnit audioUnit; - Array parameterIds; - - //============================================================================== - bool getComponentDescFromFile (const String& fileOrIdentifier); - 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, (int) supportedChannels[i].inChannels); - numOuts = jmax (numOuts, (int) 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; - } - } - - const String getCategory() const; - - //============================================================================== - AudioUnitPluginInstance (const String& fileOrIdentifier); -}; - -//============================================================================== -AudioUnitPluginInstance::AudioUnitPluginInstance (const String& fileOrIdentifier) - : fileOrIdentifier (fileOrIdentifier), - initialised (false), - wantsMidiMessages (false), - audioUnit (0), - currentBuffer (0) -{ - using namespace AudioUnitFormatHelpers; - - try - { - ++insideCallback; - - log ("Opening AU: " + fileOrIdentifier); - - if (getComponentDescFromFile (fileOrIdentifier)) - { - 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 (AudioUnitFormatHelpers::insideCallback == 0); - - if (audioUnit != 0) - { - AudioUnitUninitialize (audioUnit); - CloseComponent (audioUnit); - audioUnit = 0; - } -} - -bool AudioUnitPluginInstance::getComponentDescFromFile (const String& fileOrIdentifier) -{ - zerostruct (componentDesc); - - if (AudioUnitFormatHelpers::getComponentDescFromIdentifier (fileOrIdentifier, componentDesc, pluginName, version, manufacturer)) - return true; - - const File file (fileOrIdentifier); - if (! file.hasFileExtension (".component")) - return false; - - const char* const utf8 = fileOrIdentifier.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 ("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) -{ - if (audioUnit != 0) - { - Float64 sampleRateIn = 0, sampleRateOut = 0; - UInt32 sampleRateSize = sizeof (sampleRateIn); - AudioUnitGetProperty (audioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Input, 0, &sampleRateIn, &sampleRateSize); - AudioUnitGetProperty (audioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sampleRateOut, &sampleRateSize); - - if (sampleRateIn != sampleRate_ || sampleRateOut != sampleRate_) - { - if (initialised) - { - AudioUnitUninitialize (audioUnit); - initialised = false; - } - - Float64 sr = sampleRate_; - AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Input, 0, &sr, sizeof (Float64)); - AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sr, sizeof (Float64)); - } - } - - 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 (roundToInt (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)); - - outputBufferList.calloc (sizeof (AudioBufferList) + sizeof (AudioBuffer) * (numOuts + 1), 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); - - outputBufferList.free(); - 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)) - { - if (outCurrentBeat != 0) - *outCurrentBeat = result.ppqPosition; - - if (outCurrentTempo != 0) - *outCurrentTempo = result.bpm; - } - else - { - if (outCurrentBeat != 0) - *outCurrentBeat = 0; - - if (outCurrentTempo != 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)) - { - if (outTimeSig_Numerator != 0) - *outTimeSig_Numerator = result.timeSigNumerator; - - if (outTimeSig_Denominator != 0) - *outTimeSig_Denominator = result.timeSigDenominator; - - if (outDeltaSampleOffsetToNextBeat != 0) - *outDeltaSampleOffsetToNextBeat = 0; //xxx - - if (outCurrentMeasureDownBeat != 0) - *outCurrentMeasureDownBeat = result.ppqPositionOfLastBarStart; //xxx wrong - } - else - { - if (outDeltaSampleOffsetToNextBeat != 0) - *outDeltaSampleOffsetToNextBeat = 0; - - if (outTimeSig_Numerator != 0) - *outTimeSig_Numerator = 4; - - if (outTimeSig_Denominator != 0) - *outTimeSig_Denominator = 4; - - if (outCurrentMeasureDownBeat != 0) - *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)) - { - if (outIsPlaying != 0) - *outIsPlaying = result.isPlaying; - - if (outTransportStateChanged != 0) - { - *outTransportStateChanged = result.isPlaying != wasPlaying; - wasPlaying = result.isPlaying; - } - - if (outCurrentSampleInTimeLine != 0) - *outCurrentSampleInTimeLine = roundToInt (result.timeInSeconds * getSampleRate()); - - if (outIsCycling != 0) - *outIsCycling = false; - - if (outCycleStartBeat != 0) - *outCycleStartBeat = 0; - - if (outCycleEndBeat != 0) - *outCycleEndBeat = 0; - } - else - { - if (outIsPlaying != 0) - *outIsPlaying = false; - - if (outTransportStateChanged != 0) - *outTransportStateChanged = false; - - if (outCurrentSampleInTimeLine != 0) - *outCurrentSampleInTimeLine = 0; - - if (outIsCycling != 0) - *outIsCycling = false; - - if (outCycleStartBeat != 0) - *outCycleStartBeat = 0; - - if (outCycleEndBeat != 0) - *outCycleEndBeat = 0; - } - - return noErr; -} - - -//============================================================================== -class AudioUnitPluginWindowCocoa : public AudioProcessorEditor -{ -public: - AudioUnitPluginWindowCocoa (AudioUnitPluginInstance& plugin_, const bool createGenericViewIfNeeded) - : AudioProcessorEditor (&plugin_), - plugin (plugin_), - wrapper (0) - { - addAndMakeVisible (wrapper = new NSViewComponent()); - - setOpaque (true); - setVisible (true); - setSize (100, 100); - - createView (createGenericViewIfNeeded); - } - - ~AudioUnitPluginWindowCocoa() - { - const bool wasValid = isValid(); - - wrapper->setView (0); - - if (wasValid) - plugin.editorBeingDeleted (this); - - delete wrapper; - } - - bool isValid() const { return wrapper->getView() != 0; } - - void paint (Graphics& g) - { - g.fillAll (Colours::white); - } - - void resized() - { - wrapper->setSize (getWidth(), getHeight()); - } - -private: - AudioUnitPluginInstance& plugin; - NSViewComponent* wrapper; - - bool createView (const bool createGenericViewIfNeeded) - { - NSView* pluginView = 0; - - UInt32 dataSize = 0; - Boolean isWritable = false; - - if (AudioUnitGetPropertyInfo (plugin.audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, - 0, &dataSize, &isWritable) == noErr - && dataSize != 0 - && AudioUnitGetPropertyInfo (plugin.audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, - 0, &dataSize, &isWritable) == noErr) - { - HeapBlock info; - info.calloc (dataSize, 1); - - if (AudioUnitGetProperty (plugin.audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, - 0, info, &dataSize) == noErr) - { - NSString* viewClassName = (NSString*) (info->mCocoaAUViewClass[0]); - NSString* path = (NSString*) CFURLCopyPath (info->mCocoaAUViewBundleLocation); - NSBundle* viewBundle = [NSBundle bundleWithPath: [path autorelease]]; - Class viewClass = [viewBundle classNamed: viewClassName]; - - if ([viewClass conformsToProtocol: @protocol (AUCocoaUIBase)] - && [viewClass instancesRespondToSelector: @selector (interfaceVersion)] - && [viewClass instancesRespondToSelector: @selector (uiViewForAudioUnit: withSize:)]) - { - id factory = [[[viewClass alloc] init] autorelease]; - pluginView = [factory uiViewForAudioUnit: plugin.audioUnit - withSize: NSMakeSize (getWidth(), getHeight())]; - } - - for (int i = (dataSize - sizeof (CFURLRef)) / sizeof (CFStringRef); --i >= 0;) - { - CFRelease (info->mCocoaAUViewClass[i]); - CFRelease (info->mCocoaAUViewBundleLocation); - } - } - } - - if (createGenericViewIfNeeded && (pluginView == 0)) - pluginView = [[AUGenericView alloc] initWithAudioUnit: plugin.audioUnit]; - - wrapper->setView (pluginView); - - if (pluginView != 0) - setSize ([pluginView frame].size.width, - [pluginView frame].size.height); - - return pluginView != 0; - } -}; - -#if JUCE_SUPPORT_CARBON - -//============================================================================== -class AudioUnitPluginWindowCarbon : public AudioProcessorEditor -{ -public: - //============================================================================== - AudioUnitPluginWindowCarbon (AudioUnitPluginInstance& plugin_) - : AudioProcessorEditor (&plugin_), - plugin (plugin_), - viewComponent (0) - { - addAndMakeVisible (innerWrapper = new InnerWrapperComponent (this)); - - setOpaque (true); - setVisible (true); - setSize (400, 300); - - ComponentDescription viewList [16]; - UInt32 viewListSize = sizeof (viewList); - AudioUnitGetProperty (plugin.audioUnit, kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, - 0, &viewList, &viewListSize); - - componentRecord = FindNextComponent (0, &viewList[0]); - } - - ~AudioUnitPluginWindowCarbon() - { - innerWrapper = 0; - - if (isValid()) - plugin.editorBeingDeleted (this); - } - - bool isValid() const throw() { return componentRecord != 0; } - - //============================================================================== - void paint (Graphics& g) - { - g.fillAll (Colours::black); - } - - void resized() - { - innerWrapper->setSize (getWidth(), getHeight()); - } - - //============================================================================== - bool keyStateChanged (bool) - { - return false; - } - - bool keyPressed (const KeyPress&) - { - return false; - } - - //============================================================================== - AudioUnit getAudioUnit() const { return plugin.audioUnit; } - - AudioUnitCarbonView getViewComponent() - { - if (viewComponent == 0 && componentRecord != 0) - viewComponent = (AudioUnitCarbonView) OpenComponent (componentRecord); - - return viewComponent; - } - - void closeViewComponent() - { - if (viewComponent != 0) - { - CloseComponent (viewComponent); - viewComponent = 0; - } - } - - //============================================================================== - juce_UseDebuggingNewOperator - -private: - AudioUnitPluginInstance& plugin; - ComponentRecord* componentRecord; - AudioUnitCarbonView viewComponent; - - //============================================================================== - class InnerWrapperComponent : public CarbonViewWrapperComponent - { - public: - InnerWrapperComponent (AudioUnitPluginWindowCarbon* const owner_) - : owner (owner_) - { - } - - ~InnerWrapperComponent() - { - deleteWindow(); - } - - HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) - { - log ("Opening AU GUI: " + owner->plugin.getName()); - - AudioUnitCarbonView viewComponent = owner->getViewComponent(); - - if (viewComponent == 0) - return 0; - - Float32Point pos = { 0, 0 }; - Float32Point size = { 250, 200 }; - - HIViewRef pluginView = 0; - - AudioUnitCarbonViewCreate (viewComponent, - owner->getAudioUnit(), - windowRef, - rootView, - &pos, - &size, - (ControlRef*) &pluginView); - - return pluginView; - } - - void removeView (HIViewRef) - { - log ("Closing AU GUI: " + owner->plugin.getName()); - - owner->closeViewComponent(); - } - - private: - AudioUnitPluginWindowCarbon* const owner; - }; - - friend class InnerWrapperComponent; - ScopedPointer innerWrapper; -}; - -#endif - -//============================================================================== -AudioProcessorEditor* AudioUnitPluginInstance::createEditor() -{ - ScopedPointer w (new AudioUnitPluginWindowCocoa (*this, false)); - - if (! static_cast (static_cast (w))->isValid()) - w = 0; - -#if JUCE_SUPPORT_CARBON - if (w == 0) - { - w = new AudioUnitPluginWindowCarbon (*this); - - if (! static_cast (static_cast (w))->isValid()) - w = 0; - } -#endif - - if (w == 0) - w = new AudioUnitPluginWindowCocoa (*this, true); // use AUGenericView as a fallback - - return w.release(); -} - - -//============================================================================== -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 "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 "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 & results, - const String& fileOrIdentifier) -{ - if (! fileMightContainThisPluginType (fileOrIdentifier)) - return; - - PluginDescription desc; - desc.fileOrIdentifier = fileOrIdentifier; - desc.uid = 0; - - try - { - ScopedPointer createdInstance (createInstanceFromDescription (desc)); - AudioUnitPluginInstance* const auInstance = dynamic_cast ((AudioPluginInstance*) createdInstance); - - if (auInstance != 0) - { - auInstance->fillInPluginDescription (desc); - results.add (new PluginDescription (desc)); - } - } - catch (...) - { - // crashed while loading... - } -} - -AudioPluginInstance* AudioUnitPluginFormat::createInstanceFromDescription (const PluginDescription& desc) -{ - if (fileMightContainThisPluginType (desc.fileOrIdentifier)) - { - ScopedPointer result (new AudioUnitPluginInstance (desc.fileOrIdentifier)); - - if (result->audioUnit != 0) - { - result->initialise(); - return result.release(); - } - } - - return 0; -} - -const StringArray AudioUnitPluginFormat::searchPathsForPlugins (const FileSearchPath& /*directoriesToSearch*/, - const bool /*recursive*/) -{ - StringArray result; - ComponentRecord* comp = 0; - ComponentDescription desc; - zerostruct (desc); - - for (;;) - { - zerostruct (desc); - comp = FindNextComponent (comp, &desc); - - if (comp == 0) - break; - - GetComponentInfo (comp, &desc, 0, 0, 0); - - if (desc.componentType == kAudioUnitType_MusicDevice - || desc.componentType == kAudioUnitType_MusicEffect - || desc.componentType == kAudioUnitType_Effect - || desc.componentType == kAudioUnitType_Generator - || desc.componentType == kAudioUnitType_Panner) - { - const String s (AudioUnitFormatHelpers::createAUPluginIdentifier (desc)); - DBG (s); - result.add (s); - } - } - - return result; -} - -bool AudioUnitPluginFormat::fileMightContainThisPluginType (const String& fileOrIdentifier) -{ - ComponentDescription desc; - - String name, version, manufacturer; - if (AudioUnitFormatHelpers::getComponentDescFromIdentifier (fileOrIdentifier, desc, name, version, manufacturer)) - return FindNextComponent (0, &desc) != 0; - - const File f (fileOrIdentifier); - - return f.hasFileExtension (".component") - && f.isDirectory(); -} - -const String AudioUnitPluginFormat::getNameOfPluginFromIdentifier (const String& fileOrIdentifier) -{ - ComponentDescription desc; - String name, version, manufacturer; - AudioUnitFormatHelpers::getComponentDescFromIdentifier (fileOrIdentifier, desc, name, version, manufacturer); - - if (name.isEmpty()) - name = fileOrIdentifier; - - return name; -} - -bool AudioUnitPluginFormat::doesPluginStillExist (const PluginDescription& desc) -{ - if (desc.fileOrIdentifier.startsWithIgnoreCase (AudioUnitFormatHelpers::auIdentifierPrefix)) - return fileMightContainThisPluginType (desc.fileOrIdentifier); - else - return File (desc.fileOrIdentifier).exists(); -} - -const FileSearchPath AudioUnitPluginFormat::getDefaultLocationsToSearch() -{ - return FileSearchPath ("/(Default AudioUnit locations)"); -} - -#endif - -END_JUCE_NAMESPACE - -#undef log - -#endif +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-10 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + 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. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +#include "../../../core/juce_TargetPlatform.h" +#include "../../../../juce_Config.h" + +#if JUCE_PLUGINHOST_AU && ! (JUCE_LINUX || JUCE_WINDOWS) + +#include +#include +#include + +#if JUCE_SUPPORT_CARBON +#include +#include +#endif + +#include "../../../core/juce_StandardHeader.h" + +BEGIN_JUCE_NAMESPACE + +#include "juce_AudioUnitPluginFormat.h" +#include "../juce_PluginDescription.h" +#include "../../../threads/juce_ScopedLock.h" +#include "../../../events/juce_Timer.h" +#include "../../../core/juce_PlatformUtilities.h" +#include "../../../gui/components/layout/juce_ComponentMovementWatcher.h" +#include "../../../gui/components/windows/juce_ComponentPeer.h" +#include "../../../gui/components/special/juce_NSViewComponent.h" +#if JUCE_MAC && JUCE_SUPPORT_CARBON +#include "../../../native/mac/juce_mac_CarbonViewWrapperComponent.h" +#endif + +#if JUCE_MAC + +// 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 + +namespace AudioUnitFormatHelpers +{ + static int insideCallback = 0; + + static const String osTypeToString (OSType type) + { + char s[4]; + s[0] = (char) (((uint32) type) >> 24); + s[1] = (char) (((uint32) type) >> 16); + s[2] = (char) (((uint32) type) >> 8); + s[3] = (char) ((uint32) type); + return String (s, 4); + } + + static OSType stringToOSType (const String& s1) + { + const String s (s1 + " "); + + return (((OSType) (unsigned char) s[0]) << 24) + | (((OSType) (unsigned char) s[1]) << 16) + | (((OSType) (unsigned char) s[2]) << 8) + | ((OSType) (unsigned char) s[3]); + } + + static const char* auIdentifierPrefix = "AudioUnit:"; + + static const String createAUPluginIdentifier (const ComponentDescription& desc) + { + jassert (osTypeToString ('abcd') == "abcd"); // agh, must have got the endianness wrong.. + jassert (stringToOSType ("abcd") == (OSType) 'abcd'); // ditto + + String s (auIdentifierPrefix); + + if (desc.componentType == kAudioUnitType_MusicDevice) + s << "Synths/"; + else if (desc.componentType == kAudioUnitType_MusicEffect + || desc.componentType == kAudioUnitType_Effect) + s << "Effects/"; + else if (desc.componentType == kAudioUnitType_Generator) + s << "Generators/"; + else if (desc.componentType == kAudioUnitType_Panner) + s << "Panners/"; + + s << osTypeToString (desc.componentType) << "," + << osTypeToString (desc.componentSubType) << "," + << osTypeToString (desc.componentManufacturer); + + return s; + } + + static void getAUDetails (ComponentRecord* comp, String& name, String& manufacturer) + { + Handle componentNameHandle = NewHandle (sizeof (void*)); + Handle componentInfoHandle = NewHandle (sizeof (void*)); + + if (componentNameHandle != 0 && componentInfoHandle != 0) + { + ComponentDescription desc; + + if (GetComponentInfo (comp, &desc, componentNameHandle, componentInfoHandle, 0) == noErr) + { + ConstStr255Param nameString = (ConstStr255Param) (*componentNameHandle); + ConstStr255Param infoString = (ConstStr255Param) (*componentInfoHandle); + + if (nameString != 0 && nameString[0] != 0) + { + const String all ((const char*) nameString + 1, nameString[0]); + DBG ("name: "+ all); + + manufacturer = all.upToFirstOccurrenceOf (":", false, false).trim(); + name = all.fromFirstOccurrenceOf (":", false, false).trim(); + } + + if (infoString != 0 && infoString[0] != 0) + { + DBG ("info: " + String ((const char*) infoString + 1, infoString[0])); + } + + if (name.isEmpty()) + name = ""; + } + + DisposeHandle (componentNameHandle); + DisposeHandle (componentInfoHandle); + } + } + + static bool getComponentDescFromIdentifier (const String& fileOrIdentifier, ComponentDescription& desc, + String& name, String& version, String& manufacturer) + { + zerostruct (desc); + + if (fileOrIdentifier.startsWithIgnoreCase (auIdentifierPrefix)) + { + String s (fileOrIdentifier.substring (jmax (fileOrIdentifier.lastIndexOfChar (':'), + fileOrIdentifier.lastIndexOfChar ('/')) + 1)); + + StringArray tokens; + tokens.addTokens (s, ",", String::empty); + tokens.trim(); + tokens.removeEmptyStrings(); + + if (tokens.size() == 3) + { + desc.componentType = stringToOSType (tokens[0]); + desc.componentSubType = stringToOSType (tokens[1]); + desc.componentManufacturer = stringToOSType (tokens[2]); + + ComponentRecord* comp = FindNextComponent (0, &desc); + + if (comp != 0) + { + getAUDetails (comp, name, manufacturer); + return true; + } + } + } + + return false; + } +} + +//============================================================================== +class AudioUnitPluginWindowCarbon; +class AudioUnitPluginWindowCocoa; + +//============================================================================== +class AudioUnitPluginInstance : public AudioPluginInstance +{ +public: + //============================================================================== + ~AudioUnitPluginInstance(); + + //============================================================================== + // AudioPluginInstance methods: + + void fillInPluginDescription (PluginDescription& desc) const + { + desc.name = pluginName; + desc.fileOrIdentifier = AudioUnitFormatHelpers::createAUPluginIdentifier (componentDesc); + desc.uid = ((int) componentDesc.componentType) + ^ ((int) componentDesc.componentSubType) + ^ ((int) componentDesc.componentManufacturer); + desc.lastFileModTime = 0; + desc.pluginFormatName = "AudioUnit"; + desc.category = getCategory(); + desc.manufacturerName = manufacturer; + desc.version = version; + desc.numInputChannels = getNumInputChannels(); + desc.numOutputChannels = getNumOutputChannels(); + desc.isInstrument = (componentDesc.componentType == kAudioUnitType_MusicDevice); + } + + const String getName() const { return pluginName; } + 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 AudioUnitPluginWindowCarbon; + friend class AudioUnitPluginWindowCocoa; + friend class AudioUnitPluginFormat; + + ComponentDescription componentDesc; + String pluginName, manufacturer, version; + String fileOrIdentifier; + CriticalSection lock; + bool initialised, wantsMidiMessages, wasPlaying; + + HeapBlock outputBufferList; + AudioTimeStamp timeStamp; + AudioSampleBuffer* currentBuffer; + + AudioUnit audioUnit; + Array parameterIds; + + //============================================================================== + bool getComponentDescFromFile (const String& fileOrIdentifier); + 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, (int) supportedChannels[i].inChannels); + numOuts = jmax (numOuts, (int) 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; + } + } + + const String getCategory() const; + + //============================================================================== + AudioUnitPluginInstance (const String& fileOrIdentifier); +}; + +//============================================================================== +AudioUnitPluginInstance::AudioUnitPluginInstance (const String& fileOrIdentifier) + : fileOrIdentifier (fileOrIdentifier), + initialised (false), + wantsMidiMessages (false), + audioUnit (0), + currentBuffer (0) +{ + using namespace AudioUnitFormatHelpers; + + try + { + ++insideCallback; + + log ("Opening AU: " + fileOrIdentifier); + + if (getComponentDescFromFile (fileOrIdentifier)) + { + 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 (AudioUnitFormatHelpers::insideCallback == 0); + + if (audioUnit != 0) + { + AudioUnitUninitialize (audioUnit); + CloseComponent (audioUnit); + audioUnit = 0; + } +} + +bool AudioUnitPluginInstance::getComponentDescFromFile (const String& fileOrIdentifier) +{ + zerostruct (componentDesc); + + if (AudioUnitFormatHelpers::getComponentDescFromIdentifier (fileOrIdentifier, componentDesc, pluginName, version, manufacturer)) + return true; + + const File file (fileOrIdentifier); + if (! file.hasFileExtension (".component")) + return false; + + const char* const utf8 = fileOrIdentifier.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 ("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) +{ + if (audioUnit != 0) + { + Float64 sampleRateIn = 0, sampleRateOut = 0; + UInt32 sampleRateSize = sizeof (sampleRateIn); + AudioUnitGetProperty (audioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Input, 0, &sampleRateIn, &sampleRateSize); + AudioUnitGetProperty (audioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sampleRateOut, &sampleRateSize); + + if (sampleRateIn != sampleRate_ || sampleRateOut != sampleRate_) + { + if (initialised) + { + AudioUnitUninitialize (audioUnit); + initialised = false; + } + + Float64 sr = sampleRate_; + AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Input, 0, &sr, sizeof (Float64)); + AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sr, sizeof (Float64)); + } + } + + 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 (roundToInt (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)); + + outputBufferList.calloc (sizeof (AudioBufferList) + sizeof (AudioBuffer) * (numOuts + 1), 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); + + outputBufferList.free(); + 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)) + { + if (outCurrentBeat != 0) + *outCurrentBeat = result.ppqPosition; + + if (outCurrentTempo != 0) + *outCurrentTempo = result.bpm; + } + else + { + if (outCurrentBeat != 0) + *outCurrentBeat = 0; + + if (outCurrentTempo != 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)) + { + if (outTimeSig_Numerator != 0) + *outTimeSig_Numerator = result.timeSigNumerator; + + if (outTimeSig_Denominator != 0) + *outTimeSig_Denominator = result.timeSigDenominator; + + if (outDeltaSampleOffsetToNextBeat != 0) + *outDeltaSampleOffsetToNextBeat = 0; //xxx + + if (outCurrentMeasureDownBeat != 0) + *outCurrentMeasureDownBeat = result.ppqPositionOfLastBarStart; //xxx wrong + } + else + { + if (outDeltaSampleOffsetToNextBeat != 0) + *outDeltaSampleOffsetToNextBeat = 0; + + if (outTimeSig_Numerator != 0) + *outTimeSig_Numerator = 4; + + if (outTimeSig_Denominator != 0) + *outTimeSig_Denominator = 4; + + if (outCurrentMeasureDownBeat != 0) + *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)) + { + if (outIsPlaying != 0) + *outIsPlaying = result.isPlaying; + + if (outTransportStateChanged != 0) + { + *outTransportStateChanged = result.isPlaying != wasPlaying; + wasPlaying = result.isPlaying; + } + + if (outCurrentSampleInTimeLine != 0) + *outCurrentSampleInTimeLine = roundToInt (result.timeInSeconds * getSampleRate()); + + if (outIsCycling != 0) + *outIsCycling = false; + + if (outCycleStartBeat != 0) + *outCycleStartBeat = 0; + + if (outCycleEndBeat != 0) + *outCycleEndBeat = 0; + } + else + { + if (outIsPlaying != 0) + *outIsPlaying = false; + + if (outTransportStateChanged != 0) + *outTransportStateChanged = false; + + if (outCurrentSampleInTimeLine != 0) + *outCurrentSampleInTimeLine = 0; + + if (outIsCycling != 0) + *outIsCycling = false; + + if (outCycleStartBeat != 0) + *outCycleStartBeat = 0; + + if (outCycleEndBeat != 0) + *outCycleEndBeat = 0; + } + + return noErr; +} + + +//============================================================================== +class AudioUnitPluginWindowCocoa : public AudioProcessorEditor +{ +public: + AudioUnitPluginWindowCocoa (AudioUnitPluginInstance& plugin_, const bool createGenericViewIfNeeded) + : AudioProcessorEditor (&plugin_), + plugin (plugin_) + { + addAndMakeVisible (&wrapper); + + setOpaque (true); + setVisible (true); + setSize (100, 100); + + createView (createGenericViewIfNeeded); + } + + ~AudioUnitPluginWindowCocoa() + { + const bool wasValid = isValid(); + + wrapper.setView (0); + + if (wasValid) + plugin.editorBeingDeleted (this); + } + + bool isValid() const { return wrapper.getView() != 0; } + + void paint (Graphics& g) + { + g.fillAll (Colours::white); + } + + void resized() + { + wrapper.setSize (getWidth(), getHeight()); + } + +private: + AudioUnitPluginInstance& plugin; + NSViewComponent wrapper; + + bool createView (const bool createGenericViewIfNeeded) + { + NSView* pluginView = 0; + + UInt32 dataSize = 0; + Boolean isWritable = false; + + if (AudioUnitGetPropertyInfo (plugin.audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, + 0, &dataSize, &isWritable) == noErr + && dataSize != 0 + && AudioUnitGetPropertyInfo (plugin.audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, + 0, &dataSize, &isWritable) == noErr) + { + HeapBlock info; + info.calloc (dataSize, 1); + + if (AudioUnitGetProperty (plugin.audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, + 0, info, &dataSize) == noErr) + { + NSString* viewClassName = (NSString*) (info->mCocoaAUViewClass[0]); + NSString* path = (NSString*) CFURLCopyPath (info->mCocoaAUViewBundleLocation); + NSBundle* viewBundle = [NSBundle bundleWithPath: [path autorelease]]; + Class viewClass = [viewBundle classNamed: viewClassName]; + + if ([viewClass conformsToProtocol: @protocol (AUCocoaUIBase)] + && [viewClass instancesRespondToSelector: @selector (interfaceVersion)] + && [viewClass instancesRespondToSelector: @selector (uiViewForAudioUnit: withSize:)]) + { + id factory = [[[viewClass alloc] init] autorelease]; + pluginView = [factory uiViewForAudioUnit: plugin.audioUnit + withSize: NSMakeSize (getWidth(), getHeight())]; + } + + for (int i = (dataSize - sizeof (CFURLRef)) / sizeof (CFStringRef); --i >= 0;) + { + CFRelease (info->mCocoaAUViewClass[i]); + CFRelease (info->mCocoaAUViewBundleLocation); + } + } + } + + if (createGenericViewIfNeeded && (pluginView == 0)) + pluginView = [[AUGenericView alloc] initWithAudioUnit: plugin.audioUnit]; + + wrapper.setView (pluginView); + + if (pluginView != 0) + setSize ([pluginView frame].size.width, + [pluginView frame].size.height); + + return pluginView != 0; + } +}; + +#if JUCE_SUPPORT_CARBON + +//============================================================================== +class AudioUnitPluginWindowCarbon : public AudioProcessorEditor +{ +public: + //============================================================================== + AudioUnitPluginWindowCarbon (AudioUnitPluginInstance& plugin_) + : AudioProcessorEditor (&plugin_), + plugin (plugin_), + viewComponent (0) + { + addAndMakeVisible (innerWrapper = new InnerWrapperComponent (this)); + + setOpaque (true); + setVisible (true); + setSize (400, 300); + + ComponentDescription viewList [16]; + UInt32 viewListSize = sizeof (viewList); + AudioUnitGetProperty (plugin.audioUnit, kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, + 0, &viewList, &viewListSize); + + componentRecord = FindNextComponent (0, &viewList[0]); + } + + ~AudioUnitPluginWindowCarbon() + { + innerWrapper = 0; + + if (isValid()) + plugin.editorBeingDeleted (this); + } + + bool isValid() const throw() { return componentRecord != 0; } + + //============================================================================== + void paint (Graphics& g) + { + g.fillAll (Colours::black); + } + + void resized() + { + innerWrapper->setSize (getWidth(), getHeight()); + } + + //============================================================================== + bool keyStateChanged (bool) + { + return false; + } + + bool keyPressed (const KeyPress&) + { + return false; + } + + //============================================================================== + AudioUnit getAudioUnit() const { return plugin.audioUnit; } + + AudioUnitCarbonView getViewComponent() + { + if (viewComponent == 0 && componentRecord != 0) + viewComponent = (AudioUnitCarbonView) OpenComponent (componentRecord); + + return viewComponent; + } + + void closeViewComponent() + { + if (viewComponent != 0) + { + CloseComponent (viewComponent); + viewComponent = 0; + } + } + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + AudioUnitPluginInstance& plugin; + ComponentRecord* componentRecord; + AudioUnitCarbonView viewComponent; + + //============================================================================== + class InnerWrapperComponent : public CarbonViewWrapperComponent + { + public: + InnerWrapperComponent (AudioUnitPluginWindowCarbon* const owner_) + : owner (owner_) + { + } + + ~InnerWrapperComponent() + { + deleteWindow(); + } + + HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) + { + log ("Opening AU GUI: " + owner->plugin.getName()); + + AudioUnitCarbonView viewComponent = owner->getViewComponent(); + + if (viewComponent == 0) + return 0; + + Float32Point pos = { 0, 0 }; + Float32Point size = { 250, 200 }; + + HIViewRef pluginView = 0; + + AudioUnitCarbonViewCreate (viewComponent, + owner->getAudioUnit(), + windowRef, + rootView, + &pos, + &size, + (ControlRef*) &pluginView); + + return pluginView; + } + + void removeView (HIViewRef) + { + log ("Closing AU GUI: " + owner->plugin.getName()); + + owner->closeViewComponent(); + } + + private: + AudioUnitPluginWindowCarbon* const owner; + }; + + friend class InnerWrapperComponent; + ScopedPointer innerWrapper; +}; + +#endif + +//============================================================================== +AudioProcessorEditor* AudioUnitPluginInstance::createEditor() +{ + ScopedPointer w (new AudioUnitPluginWindowCocoa (*this, false)); + + if (! static_cast (static_cast (w))->isValid()) + w = 0; + +#if JUCE_SUPPORT_CARBON + if (w == 0) + { + w = new AudioUnitPluginWindowCarbon (*this); + + if (! static_cast (static_cast (w))->isValid()) + w = 0; + } +#endif + + if (w == 0) + w = new AudioUnitPluginWindowCocoa (*this, true); // use AUGenericView as a fallback + + return w.release(); +} + + +//============================================================================== +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 "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 "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 & results, + const String& fileOrIdentifier) +{ + if (! fileMightContainThisPluginType (fileOrIdentifier)) + return; + + PluginDescription desc; + desc.fileOrIdentifier = fileOrIdentifier; + desc.uid = 0; + + try + { + ScopedPointer createdInstance (createInstanceFromDescription (desc)); + AudioUnitPluginInstance* const auInstance = dynamic_cast ((AudioPluginInstance*) createdInstance); + + if (auInstance != 0) + { + auInstance->fillInPluginDescription (desc); + results.add (new PluginDescription (desc)); + } + } + catch (...) + { + // crashed while loading... + } +} + +AudioPluginInstance* AudioUnitPluginFormat::createInstanceFromDescription (const PluginDescription& desc) +{ + if (fileMightContainThisPluginType (desc.fileOrIdentifier)) + { + ScopedPointer result (new AudioUnitPluginInstance (desc.fileOrIdentifier)); + + if (result->audioUnit != 0) + { + result->initialise(); + return result.release(); + } + } + + return 0; +} + +const StringArray AudioUnitPluginFormat::searchPathsForPlugins (const FileSearchPath& /*directoriesToSearch*/, + const bool /*recursive*/) +{ + StringArray result; + ComponentRecord* comp = 0; + ComponentDescription desc; + zerostruct (desc); + + for (;;) + { + zerostruct (desc); + comp = FindNextComponent (comp, &desc); + + if (comp == 0) + break; + + GetComponentInfo (comp, &desc, 0, 0, 0); + + if (desc.componentType == kAudioUnitType_MusicDevice + || desc.componentType == kAudioUnitType_MusicEffect + || desc.componentType == kAudioUnitType_Effect + || desc.componentType == kAudioUnitType_Generator + || desc.componentType == kAudioUnitType_Panner) + { + const String s (AudioUnitFormatHelpers::createAUPluginIdentifier (desc)); + DBG (s); + result.add (s); + } + } + + return result; +} + +bool AudioUnitPluginFormat::fileMightContainThisPluginType (const String& fileOrIdentifier) +{ + ComponentDescription desc; + + String name, version, manufacturer; + if (AudioUnitFormatHelpers::getComponentDescFromIdentifier (fileOrIdentifier, desc, name, version, manufacturer)) + return FindNextComponent (0, &desc) != 0; + + const File f (fileOrIdentifier); + + return f.hasFileExtension (".component") + && f.isDirectory(); +} + +const String AudioUnitPluginFormat::getNameOfPluginFromIdentifier (const String& fileOrIdentifier) +{ + ComponentDescription desc; + String name, version, manufacturer; + AudioUnitFormatHelpers::getComponentDescFromIdentifier (fileOrIdentifier, desc, name, version, manufacturer); + + if (name.isEmpty()) + name = fileOrIdentifier; + + return name; +} + +bool AudioUnitPluginFormat::doesPluginStillExist (const PluginDescription& desc) +{ + if (desc.fileOrIdentifier.startsWithIgnoreCase (AudioUnitFormatHelpers::auIdentifierPrefix)) + return fileMightContainThisPluginType (desc.fileOrIdentifier); + else + return File (desc.fileOrIdentifier).exists(); +} + +const FileSearchPath AudioUnitPluginFormat::getDefaultLocationsToSearch() +{ + return FileSearchPath ("/(Default AudioUnit locations)"); +} + +#endif + +END_JUCE_NAMESPACE + +#undef log + +#endif diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index fab164423d..a4f3f15222 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 48 +#define JUCE_BUILDNUMBER 49 /** Current Juce version number. diff --git a/src/gui/components/filebrowser/juce_FileChooserDialogBox.cpp b/src/gui/components/filebrowser/juce_FileChooserDialogBox.cpp index b83ea71659..3d26c8e4bb 100644 --- a/src/gui/components/filebrowser/juce_FileChooserDialogBox.cpp +++ b/src/gui/components/filebrowser/juce_FileChooserDialogBox.cpp @@ -42,35 +42,19 @@ FileChooserDialogBox::FileChooserDialogBox (const String& name, : ResizableWindow (name, backgroundColour, true), warnAboutOverwritingExistingFiles (warnAboutOverwritingExistingFiles_) { - content = new ContentComponent(); - content->setName (name); - content->instructions = instructions; - content->chooserComponent = &chooserComponent; - - content->addAndMakeVisible (&chooserComponent); - - content->okButton = new TextButton (chooserComponent.getActionVerb()); - content->addAndMakeVisible (content->okButton); - content->okButton->addButtonListener (this); - content->okButton->setEnabled (chooserComponent.currentFileIsValid()); - content->okButton->addShortcut (KeyPress (KeyPress::returnKey, 0, 0)); - - content->cancelButton = new TextButton (TRANS("Cancel")); - content->addAndMakeVisible (content->cancelButton); - content->cancelButton->addButtonListener (this); - content->cancelButton->addShortcut (KeyPress (KeyPress::escapeKey, 0, 0)); - - setContentComponent (content); + setContentComponent (content = new ContentComponent (name, instructions, chooserComponent)); setResizable (true, true); setResizeLimits (300, 300, 1200, 1000); - content->chooserComponent->addListener (this); + content->okButton.addButtonListener (this); + content->cancelButton.addButtonListener (this); + content->chooserComponent.addListener (this); } FileChooserDialogBox::~FileChooserDialogBox() { - content->chooserComponent->removeListener (this); + content->chooserComponent.removeListener (this); } //============================================================================== @@ -83,7 +67,7 @@ bool FileChooserDialogBox::showAt (int x, int y, int w, int h) { if (w <= 0) { - Component* const previewComp = content->chooserComponent->getPreviewComponent(); + Component* const previewComp = content->chooserComponent.getPreviewComponent(); if (previewComp != 0) w = 400 + previewComp->getWidth(); else @@ -106,16 +90,16 @@ bool FileChooserDialogBox::showAt (int x, int y, int w, int h) //============================================================================== void FileChooserDialogBox::buttonClicked (Button* button) { - if (button == content->okButton) + if (button == &(content->okButton)) { if (warnAboutOverwritingExistingFiles - && content->chooserComponent->isSaveMode() - && content->chooserComponent->getSelectedFile(0).exists()) + && content->chooserComponent.isSaveMode() + && content->chooserComponent.getSelectedFile(0).exists()) { if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, TRANS("File already exists"), TRANS("There's already a file called:") - + "\n\n" + content->chooserComponent->getSelectedFile(0).getFullPathName() + + "\n\n" + content->chooserComponent.getSelectedFile(0).getFullPathName() + "\n\n" + TRANS("Are you sure you want to overwrite it?"), TRANS("overwrite"), TRANS("cancel"))) @@ -126,8 +110,10 @@ void FileChooserDialogBox::buttonClicked (Button* button) exitModalState (1); } - else if (button == content->cancelButton) + else if (button == &(content->cancelButton)) + { closeButtonPressed(); + } } void FileChooserDialogBox::closeButtonPressed() @@ -137,7 +123,7 @@ void FileChooserDialogBox::closeButtonPressed() void FileChooserDialogBox::selectionChanged() { - content->okButton->setEnabled (content->chooserComponent->currentFileIsValid()); + content->okButton.setEnabled (content->chooserComponent.currentFileIsValid()); } void FileChooserDialogBox::fileClicked (const File&, const MouseEvent&) @@ -147,19 +133,30 @@ void FileChooserDialogBox::fileClicked (const File&, const MouseEvent&) void FileChooserDialogBox::fileDoubleClicked (const File&) { selectionChanged(); - content->okButton->triggerClick(); + content->okButton.triggerClick(); } //============================================================================== -FileChooserDialogBox::ContentComponent::ContentComponent() +FileChooserDialogBox::ContentComponent::ContentComponent (const String& name, const String& instructions_, FileBrowserComponent& chooserComponent_) + : Component (name), instructions (instructions_), + chooserComponent (chooserComponent_), + okButton (chooserComponent_.getActionVerb()), + cancelButton (TRANS ("Cancel")) { + addAndMakeVisible (&chooserComponent); + + addAndMakeVisible (&okButton); + okButton.setEnabled (chooserComponent.currentFileIsValid()); + okButton.addShortcut (KeyPress (KeyPress::returnKey, 0, 0)); + + addAndMakeVisible (&cancelButton); + cancelButton.addShortcut (KeyPress (KeyPress::escapeKey, 0, 0)); + setInterceptsMouseClicks (false, true); } FileChooserDialogBox::ContentComponent::~ContentComponent() { - delete okButton; - delete cancelButton; } void FileChooserDialogBox::ContentComponent::paint (Graphics& g) @@ -178,13 +175,13 @@ void FileChooserDialogBox::ContentComponent::resized() const int buttonHeight = 26; const int buttonY = getHeight() - buttonHeight - 8; - chooserComponent->setBounds (0, y, getWidth(), buttonY - y - 20); + chooserComponent.setBounds (0, y, getWidth(), buttonY - y - 20); - okButton->setBounds (proportionOfWidth (0.25f), buttonY, - proportionOfWidth (0.2f), buttonHeight); + okButton.setBounds (proportionOfWidth (0.25f), buttonY, + proportionOfWidth (0.2f), buttonHeight); - cancelButton->setBounds (proportionOfWidth (0.55f), buttonY, - proportionOfWidth (0.2f), buttonHeight); + cancelButton.setBounds (proportionOfWidth (0.55f), buttonY, + proportionOfWidth (0.2f), buttonHeight); } diff --git a/src/gui/components/filebrowser/juce_FileChooserDialogBox.h b/src/gui/components/filebrowser/juce_FileChooserDialogBox.h index b2af90e6d9..d44a8ecb8c 100644 --- a/src/gui/components/filebrowser/juce_FileChooserDialogBox.h +++ b/src/gui/components/filebrowser/juce_FileChooserDialogBox.h @@ -145,7 +145,7 @@ private: class ContentComponent : public Component { public: - ContentComponent(); + ContentComponent (const String& name, const String& instructions, FileBrowserComponent& chooserComponent); ~ContentComponent(); void paint (Graphics& g); @@ -154,10 +154,8 @@ private: String instructions; GlyphArrangement text; - FileBrowserComponent* chooserComponent; - FilePreviewComponent* previewComponent; - TextButton* okButton; - TextButton* cancelButton; + FileBrowserComponent& chooserComponent; + TextButton okButton, cancelButton; }; ContentComponent* content; diff --git a/src/gui/components/juce_Component.h b/src/gui/components/juce_Component.h index b66f075e52..8c94df4a41 100644 --- a/src/gui/components/juce_Component.h +++ b/src/gui/components/juce_Component.h @@ -1978,6 +1978,9 @@ public: /** Returns the component that this pointer refers to, or null if the component no longer exists. */ const ComponentType* operator->() const throw() { jassert (comp != 0); return comp; } + /** If the component is valid, this deletes it and sets this pointer to null. */ + void deleteAndZero() { delete comp; jassert (comp == 0); } + //============================================================================== juce_UseDebuggingNewOperator diff --git a/src/gui/components/layout/juce_MultiDocumentPanel.cpp b/src/gui/components/layout/juce_MultiDocumentPanel.cpp index d2bbc7ffe0..f818c76c9a 100644 --- a/src/gui/components/layout/juce_MultiDocumentPanel.cpp +++ b/src/gui/components/layout/juce_MultiDocumentPanel.cpp @@ -115,7 +115,6 @@ public: //============================================================================== MultiDocumentPanel::MultiDocumentPanel() : mode (MaximisedWindowsWithTabs), - tabComponent (0), backgroundColour (Colours::lightblue), maximumNumDocuments (0), numDocsBeforeTabsUsed (0) @@ -309,7 +308,7 @@ bool MultiDocumentPanel::closeDocument (Component* component, delete component; if (tabComponent != 0 && tabComponent->getNumTabs() <= numDocsBeforeTabsUsed) - deleteAndZero (tabComponent); + tabComponent = 0; components.removeValue (component); @@ -410,7 +409,7 @@ void MultiDocumentPanel::setLayoutMode (const LayoutMode newLayoutMode) if (mode == FloatingWindows) { - deleteAndZero (tabComponent); + tabComponent = 0; } else { diff --git a/src/gui/components/layout/juce_MultiDocumentPanel.h b/src/gui/components/layout/juce_MultiDocumentPanel.h index 1eead385c7..e31f65bebd 100644 --- a/src/gui/components/layout/juce_MultiDocumentPanel.h +++ b/src/gui/components/layout/juce_MultiDocumentPanel.h @@ -290,7 +290,7 @@ public: private: LayoutMode mode; Array components; - TabbedComponent* tabComponent; + ScopedPointer tabComponent; Colour backgroundColour; int maximumNumDocuments, numDocsBeforeTabsUsed; diff --git a/src/gui/components/windows/juce_ResizableWindow.cpp b/src/gui/components/windows/juce_ResizableWindow.cpp index 9dfe875b8d..a9b6e16568 100644 --- a/src/gui/components/windows/juce_ResizableWindow.cpp +++ b/src/gui/components/windows/juce_ResizableWindow.cpp @@ -78,8 +78,7 @@ ResizableWindow::~ResizableWindow() { resizableCorner = 0; resizableBorder = 0; - delete static_cast (contentComponent); - contentComponent = 0; + contentComponent.deleteAndZero(); // have you been adding your own components directly to this window..? tut tut tut. // Read the instructions for using a ResizableWindow! @@ -106,8 +105,8 @@ void ResizableWindow::setContentComponent (Component* const newContentComponent, if (newContentComponent != static_cast (contentComponent)) { if (deleteOldOne) - delete static_cast (contentComponent); // (avoid using a scoped pointer for this, so that it survives - // external deletion of the content comp) + contentComponent.deleteAndZero(); // (avoid using a scoped pointer for this, so that it survives + // external deletion of the content comp) else removeChildComponent (contentComponent); diff --git a/src/gui/graphics/drawables/juce_SVGParser.cpp b/src/gui/graphics/drawables/juce_SVGParser.cpp index bf481dc7f6..3cafc83882 100644 --- a/src/gui/graphics/drawables/juce_SVGParser.cpp +++ b/src/gui/graphics/drawables/juce_SVGParser.cpp @@ -830,12 +830,12 @@ private: Path path; Drawable* s = parseShape (*e, path); - delete s; + delete s; // xxx not finished! } else if (e->hasTagName ("tspan")) { Drawable* s = parseText (*e); - delete s; + delete s; // xxx not finished! } } diff --git a/src/io/network/juce_Socket.cpp b/src/io/network/juce_Socket.cpp index 10c6e67f77..b18ee67d01 100644 --- a/src/io/network/juce_Socket.cpp +++ b/src/io/network/juce_Socket.cpp @@ -546,7 +546,7 @@ DatagramSocket::~DatagramSocket() { close(); - delete ((struct sockaddr_in*) serverAddress); + delete static_cast (serverAddress); serverAddress = 0; } diff --git a/src/native/common/juce_posix_NamedPipe.cpp b/src/native/common/juce_posix_NamedPipe.cpp index 9a741c125a..ce2f622d54 100644 --- a/src/native/common/juce_posix_NamedPipe.cpp +++ b/src/native/common/juce_posix_NamedPipe.cpp @@ -40,9 +40,9 @@ struct NamedPipeInternal void NamedPipe::cancelPendingReads() { - while (internal != 0 && ((NamedPipeInternal*) internal)->blocked) + while (internal != 0 && static_cast (internal)->blocked) { - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = static_cast (internal); intern->stopReadOperation = true; @@ -60,7 +60,7 @@ void NamedPipe::cancelPendingReads() void NamedPipe::close() { - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = static_cast (internal); if (intern != 0) { @@ -120,7 +120,7 @@ bool NamedPipe::openInternal (const String& pipeName, const bool createPipe) int NamedPipe::read (void* destBuffer, int maxBytesToRead, int /*timeOutMilliseconds*/) { int bytesRead = -1; - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = static_cast (internal); if (intern != 0) { @@ -168,7 +168,7 @@ int NamedPipe::read (void* destBuffer, int maxBytesToRead, int /*timeOutMillisec int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds) { int bytesWritten = -1; - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = static_cast (internal); if (intern != 0) { diff --git a/src/native/linux/juce_linux_Midi.cpp b/src/native/linux/juce_linux_Midi.cpp index 2e3932dc66..52f86d8751 100644 --- a/src/native/linux/juce_linux_Midi.cpp +++ b/src/native/linux/juce_linux_Midi.cpp @@ -250,8 +250,7 @@ MidiOutput* MidiOutput::createNewDevice (const String& deviceName) MidiOutput::~MidiOutput() { - MidiOutputDevice* const device = (MidiOutputDevice*) internal; - delete device; + delete static_cast (internal); } void MidiOutput::reset() @@ -269,7 +268,7 @@ void MidiOutput::setVolume (float leftVol, float rightVol) void MidiOutput::sendMessageNow (const MidiMessage& message) { - ((MidiOutputDevice*) internal)->sendMessageNow (message); + static_cast (internal)->sendMessageNow (message); } @@ -365,18 +364,17 @@ MidiInput::MidiInput (const String& name_) MidiInput::~MidiInput() { stop(); - MidiInputThread* const thread = (MidiInputThread*) internal; - delete thread; + delete static_cast (internal); } void MidiInput::start() { - ((MidiInputThread*) internal)->startThread(); + static_cast (internal)->startThread(); } void MidiInput::stop() { - ((MidiInputThread*) internal)->stopThread (3000); + static_cast (internal)->stopThread (3000); } int MidiInput::getDefaultDeviceIndex() diff --git a/src/native/mac/juce_mac_CoreMidi.cpp b/src/native/mac/juce_mac_CoreMidi.cpp index 0539945dcf..fb137e7f36 100644 --- a/src/native/mac/juce_mac_CoreMidi.cpp +++ b/src/native/mac/juce_mac_CoreMidi.cpp @@ -308,7 +308,7 @@ MidiOutput* MidiOutput::createNewDevice (const String& deviceName) MidiOutput::~MidiOutput() { - delete (MidiPortAndEndpoint*) internal; + delete static_cast (internal); } void MidiOutput::reset() @@ -326,7 +326,7 @@ void MidiOutput::setVolume (float /*leftVol*/, float /*rightVol*/) void MidiOutput::sendMessageNow (const MidiMessage& message) { - MidiPortAndEndpoint* const mpe = (MidiPortAndEndpoint*) internal; + MidiPortAndEndpoint* const mpe = static_cast (internal); if (message.isSysEx()) { @@ -619,7 +619,7 @@ MidiInput::MidiInput (const String& name_) MidiInput::~MidiInput() { - MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; + MidiPortAndCallback* const mpc = static_cast (internal); mpc->active = false; { @@ -637,13 +637,13 @@ MidiInput::~MidiInput() void MidiInput::start() { const ScopedLock sl (CoreMidiCallbacks::callbackLock); - ((MidiPortAndCallback*) internal)->active = true; + static_cast (internal)->active = true; } void MidiInput::stop() { const ScopedLock sl (CoreMidiCallbacks::callbackLock); - ((MidiPortAndCallback*) internal)->active = false; + static_cast (internal)->active = false; } #undef log diff --git a/src/native/windows/juce_win32_OpenGLComponent.cpp b/src/native/windows/juce_win32_OpenGLComponent.cpp index 651c5f482d..76e4562a3b 100644 --- a/src/native/windows/juce_win32_OpenGLComponent.cpp +++ b/src/native/windows/juce_win32_OpenGLComponent.cpp @@ -81,7 +81,6 @@ public: HGLRC contextToShareWith, const OpenGLPixelFormat& pixelFormat) : renderContext (0), - nativeWindow (0), dc (0), component (component_) { @@ -117,7 +116,7 @@ public: { deleteContext(); ReleaseDC ((HWND) nativeWindow->getNativeHandle(), dc); - delete nativeWindow; + nativeWindow = 0; } void deleteContext() @@ -270,7 +269,7 @@ public: // old one and create a new one.. jassert (nativeWindow != 0); ReleaseDC ((HWND) nativeWindow->getNativeHandle(), dc); - delete nativeWindow; + nativeWindow = 0; createNativeWindow(); @@ -385,7 +384,7 @@ public: HGLRC renderContext; private: - Win32ComponentPeer* nativeWindow; + ScopedPointer nativeWindow; Component* const component; HDC dc; diff --git a/src/native/windows/juce_win32_WASAPI.cpp b/src/native/windows/juce_win32_WASAPI.cpp index cd0a470ed8..fdd6802c91 100644 --- a/src/native/windows/juce_win32_WASAPI.cpp +++ b/src/native/windows/juce_win32_WASAPI.cpp @@ -584,9 +584,7 @@ public: Thread ("Juce WASAPI"), isOpen_ (false), isStarted (false), - outputDevice (0), outputDeviceId (outputDeviceId_), - inputDevice (0), inputDeviceId (inputDeviceId_), useExclusiveMode (useExclusiveMode_), currentBufferSizeSamples (0), @@ -598,9 +596,6 @@ public: ~WASAPIAudioIODevice() { close(); - - deleteAndZero (inputDevice); - deleteAndZero (outputDevice); } bool initialise() @@ -624,7 +619,8 @@ public: } else { - WASAPIDeviceBase* const d = inputDevice != 0 ? (WASAPIDeviceBase*) inputDevice : (WASAPIDeviceBase*) outputDevice; + WASAPIDeviceBase* d = inputDevice != 0 ? static_cast (inputDevice) + : static_cast (outputDevice); defaultSampleRate = d->defaultSampleRate; minBufferSize = d->minBufferSize; defaultBufferSize = d->defaultBufferSize; @@ -718,6 +714,7 @@ public: if (inputDevice != 0) ResetEvent (inputDevice->clientEvent); + if (outputDevice != 0) ResetEvent (outputDevice->clientEvent); @@ -891,8 +888,8 @@ public: private: // Device stats... - WASAPIInputDevice* inputDevice; - WASAPIOutputDevice* outputDevice; + ScopedPointer inputDevice; + ScopedPointer outputDevice; const bool useExclusiveMode; double defaultSampleRate; int minBufferSize, defaultBufferSize; diff --git a/src/native/windows/juce_win32_Windowing.cpp b/src/native/windows/juce_win32_Windowing.cpp index aee0478b0a..34f8159745 100644 --- a/src/native/windows/juce_win32_Windowing.cpp +++ b/src/native/windows/juce_win32_Windowing.cpp @@ -392,7 +392,6 @@ public: isMouseOver (false), hasCreatedCaret (false), currentWindowIcon (0), - taskBarIcon (0), dropTarget (0) { callFunctionIfNotLocked (&createWindowCallback, this); @@ -407,16 +406,12 @@ public: if (shadower != 0) shadower->setOwner (component); } - else - { - shadower = 0; - } } ~Win32ComponentPeer() { setTaskBarIcon (Image()); - deleteAndZero (shadower); + shadower = 0; // do this before the next bit to avoid messages arriving for this window // before it's destroyed @@ -779,7 +774,7 @@ public: taskBarIcon->uFlags = 0; Shell_NotifyIcon (NIM_DELETE, taskBarIcon); DestroyIcon (taskBarIcon->hIcon); - deleteAndZero (taskBarIcon); + taskBarIcon = 0; } } @@ -846,11 +841,11 @@ public: private: HWND hwnd; - DropShadower* shadower; + ScopedPointer shadower; bool fullScreen, isDragging, isMouseOver, hasCreatedCaret; BorderSize windowBorder; HICON currentWindowIcon; - NOTIFYICONDATA* taskBarIcon; + ScopedPointer taskBarIcon; IDropTarget* dropTarget; //==============================================================================