Browse Source

tweak to RTAS shutdown for PT8; added tooltips for the TableListBox; started adding some iphone audio code (not yet usable)

tags/2021-05-28
Julian Storer 16 years ago
parent
commit
facb48b04c
13 changed files with 905 additions and 246 deletions
  1. +3
    -0
      extras/audio plugins/wrapper/RTAS/juce_RTAS_MacUtilities.mm
  2. +441
    -117
      juce_amalgamated.cpp
  3. +6
    -2
      juce_amalgamated.h
  4. +15
    -1
      src/gui/components/controls/juce_TableListBox.cpp
  5. +4
    -0
      src/gui/components/controls/juce_TableListBox.h
  6. +2
    -2
      src/gui/components/controls/juce_TreeView.cpp
  7. +1
    -1
      src/gui/components/menus/juce_MenuBarComponent.cpp
  8. +1
    -1
      src/gui/components/special/juce_QuickTimeMovieComponent.h
  9. +1
    -1
      src/gui/graphics/fonts/juce_GlyphArrangement.h
  10. +372
    -104
      src/native/mac/juce_iphone_Audio.cpp
  11. +56
    -13
      src/native/mac/juce_iphone_MiscUtilities.mm
  12. +0
    -2
      src/native/mac/juce_mac_NativeIncludes.h
  13. +3
    -2
      src/native/windows/juce_win32_ASIO.cpp

+ 3
- 0
extras/audio plugins/wrapper/RTAS/juce_RTAS_MacUtilities.mm View File

@@ -108,6 +108,9 @@ void removeSubWindow (void* nsWindow, Component* comp)
[hostWindow removeChildWindow: pluginWindow];
comp->removeFromDesktop();
[hostWindow release];
for (int i = 20; --i >= 0;)
MessageManager::getInstance()->runDispatchLoopUntil (1);
}
static bool isJuceWindow (WindowRef w) throw()


+ 441
- 117
juce_amalgamated.cpp View File

@@ -735,8 +735,6 @@ public:

#if MACOS_10_4_OR_EARLIER
#include <GLUT/glut.h>
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif

#endif // __JUCE_MAC_NATIVEINCLUDES_JUCEHEADER__
@@ -47555,7 +47553,8 @@ BEGIN_JUCE_NAMESPACE

static const tchar* const tableColumnPropertyTag = T("_tableColumnID");

class TableListRowComp : public Component
class TableListRowComp : public Component,
public TooltipClient
{
public:
TableListRowComp (TableListBox& owner_)
@@ -47759,6 +47758,19 @@ public:
owner.getModel()->cellDoubleClicked (row, columnId, e);
}

const String getTooltip()
{
int x, y;
getMouseXYRelative (x, y);

const int columnId = owner.getHeader()->getColumnIdAtX (x);

if (columnId != 0 && owner.getModel() != 0)
return owner.getModel()->getCellTooltip (row, columnId);

return String::empty;
}

juce_UseDebuggingNewOperator

private:
@@ -244743,11 +244755,12 @@ public:
AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
{
// ASIO can't open two different devices for input and output - they must be the same one.
jassert (inputDeviceName == outputDeviceName || outputDeviceName.isEmpty() || inputDeviceName.isEmpty());
(void) inputDeviceName;
jassert (hasScanned); // need to call scanForDevices() before doing this

const int index = deviceNames.indexOf (outputDeviceName);
const int index = deviceNames.indexOf (outputDeviceName.isNotEmpty() ? outputDeviceName
: inputDeviceName);

if (index >= 0)
{
@@ -258363,33 +258376,76 @@ void PlatformUtilities::addItemToDock (const File& file)

#if ! JUCE_ONLY_BUILD_CORE_LIBRARY

bool AlertWindow::showNativeDialogBox (const String& title,
const String& bodyText,
bool isOkCancel)
END_JUCE_NAMESPACE

@interface JuceAlertBoxDelegate : NSObject
{
@public
bool clickedOk;
}

- (void) alertView: (UIAlertView*) alertView clickedButtonAtIndex: (NSInteger) buttonIndex;

@end

@implementation JuceAlertBoxDelegate

- (void) alertView: (UIAlertView*) alertView clickedButtonAtIndex: (NSInteger) buttonIndex
{
clickedOk = (buttonIndex == 0);
alertView.hidden = true;
}

@end

BEGIN_JUCE_NAMESPACE

// (This function is used directly by other bits of code)
bool juce_iPhoneShowModalAlert (const String& title,
const String& bodyText,
NSString* okButtonText,
NSString* cancelButtonText)
{
const ScopedAutoReleasePool pool;

UIAlertView *alert = [[[UIAlertView alloc] initWithTitle: juceStringToNS (title)
message: juceStringToNS (title)
delegate: nil
cancelButtonTitle: @"OK"
otherButtonTitles: (isOkCancel ? @"Cancel" : nil), nil] autorelease];
alert.cancelButtonIndex = alert.firstOtherButtonIndex;
JuceAlertBoxDelegate* callback = [[JuceAlertBoxDelegate alloc] init];

UIAlertView* alert = [[UIAlertView alloc] initWithTitle: juceStringToNS (title)
message: juceStringToNS (bodyText)
delegate: callback
cancelButtonTitle: okButtonText
otherButtonTitles: cancelButtonText, nil];
[alert retain];
[alert show];

// xxx need to use a delegate to find which button was clicked
return false;
while (! alert.hidden && alert.superview != nil)
[[NSRunLoop mainRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];

const bool result = callback->clickedOk;
[alert release];
[callback release];

return result;
}

bool AlertWindow::showNativeDialogBox (const String& title,
const String& bodyText,
bool isOkCancel)
{
return juce_iPhoneShowModalAlert (title, bodyText,
@"OK",
isOkCancel ? @"Cancel" : nil);
}

bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& files, const bool canMoveFiles)
{
jassertfalse // not implemented!
jassertfalse // no such thing on the iphone!
return false;
}

bool DragAndDropContainer::performExternalDragDropOfText (const String& text)
{
jassertfalse // not implemented!
jassertfalse // no such thing on the iphone!
return false;
}

@@ -261169,37 +261225,43 @@ bool WebBrowserComponent::pageAboutToLoad (const String& url)
// compiled on its own).
#if JUCE_INCLUDED_FILE

class IPhoneAudioIODevice : public AudioIODeviceType
class IPhoneAudioIODevice : public AudioIODevice
{
public:

IPhoneAudioIODevice (const String& deviceName, const bool isInput_)
IPhoneAudioIODevice (const String& deviceName)
: AudioIODevice (deviceName, T("Audio")),
isInput (isInput_),
isOpen_ (false),
isStarted (false)
audioUnit (0),
isRunning (false),
callback (0),
actualBufferSize (0),
floatData (1, 2)
{
numInputChannels = 2;
numOutputChannels = 2;
preferredBufferSize = 0;

AudioSessionInitialize (0, 0, interruptionListenerStatic, this);
updateDeviceInfo();
}

~IPhoneAudioIODeviceType()
~IPhoneAudioIODevice()
{
close();
}

const StringArray getOutputChannelNames()
{
StringArray s;
if (! isInput)
{
s.add ("Left");
s.add ("Right");
}
s.add ("Left");
s.add ("Right");
return s;
}

const StringArray getInputChannelNames()
{
StringArray s;
if (isInput)
if (audioInputIsAvailable)
{
s.add ("Left");
s.add ("Right");
@@ -261209,134 +261271,150 @@ public:

int getNumSampleRates()
{
return sampleRates.size();
return 1;
}

double getSampleRate (int index)
{
return sampleRates [index];
return sampleRate;
}

int getNumBufferSizesAvailable()
{
return bufferSizes.size();
return 1;
}

int getBufferSizeSamples (int index)
{
return bufferSizes [index];
return getDefaultBufferSize();
}

int getDefaultBufferSize()
{
for (int i = 0; i < getNumBufferSizesAvailable(); ++i)
if (getBufferSizeSamples(i) >= 512)
return getBufferSizeSamples(i);

return 512;
return 1024;
}

const String open (const BitArray& inputChannels,
const BitArray& outputChannels,
double sampleRate,
int bufferSizeSamples)
int bufferSize)
{
isOpen_ = true;

if (bufferSizeSamples <= 0)
bufferSizeSamples = getDefaultBufferSize();
close();

lastError = String::empty;
preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize;

isOpen_ = lastError.isEmpty();
// xxx set up channel mapping

activeOutputChans = outputChannels;
activeOutputChans.setRange (2, activeOutputChans.getHighestBit(), false);
numOutputChannels = activeOutputChans.countNumberOfSetBits();
monoOutputChannelNumber = activeOutputChans.findNextSetBit (0);

activeInputChans = inputChannels;
activeInputChans.setRange (2, activeInputChans.getHighestBit(), false);
numInputChannels = activeInputChans.countNumberOfSetBits();
monoInputChannelNumber = activeInputChans.findNextSetBit (0);

AudioSessionSetActive (true);

UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord;
AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof (audioCategory), &audioCategory);
AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange, propertyChangedStatic, this);

fixAudioRouteIfSetToReceiver();
updateDeviceInfo();

Float32 bufferDuration = preferredBufferSize / sampleRate;
AudioSessionSetProperty (kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof (bufferDuration), &bufferDuration);
actualBufferSize = preferredBufferSize;

prepareFloatBuffers();

isRunning = true;
propertyChanged (0, 0, 0); // creates and starts the AU

lastError = audioUnit != 0 ? String::empty
: T("Couldn't open the device");
return lastError;
}

void close()
{
isOpen_ = false;
if (isRunning)
{
isRunning = false;
AudioSessionSetActive (false);

if (audioUnit != 0)
{
AudioComponentInstanceDispose (audioUnit);
audioUnit = 0;
}
}
}

bool isOpen()
{
return isOpen_;
return isRunning;
}

int getCurrentBufferSizeSamples()
{
return internal != 0 ? internal->getBufferSize() : 512;
return actualBufferSize;
}

double getCurrentSampleRate()
{
return internal != 0 ? internal->getSampleRate() : 0;
return sampleRate;
}

int getCurrentBitDepth()
{
return 32; // no way to find out, so just assume it's high..
return 16;
}

const BitArray getActiveOutputChannels() const
{
return internal != 0 ? internal->activeOutputChans : BitArray();
return activeOutputChans;
}

const BitArray getActiveInputChannels() const
{
BitArray chans;

if (internal != 0)
{
chans = internal->activeInputChans;

if (internal->inputDevice != 0)
chans.orWith (internal->inputDevice->activeInputChans);
}

return chans;
return activeInputChans;
}

int getOutputLatencyInSamples()
{
if (internal == 0)
return 0;

// this seems like a good guess at getting the latency right - comparing
// this with a round-trip measurement, it gets it to within a few millisecs
// for the built-in mac soundcard
return internal->outputLatency + internal->getBufferSize() * 2;
return 0; //xxx
}

int getInputLatencyInSamples()
{
if (internal == 0)
return 0;

return internal->inputLatency + internal->getBufferSize() * 2;
return 0; //xxx
}

void start (AudioIODeviceCallback* callback)
void start (AudioIODeviceCallback* callback_)
{
if (internal != 0 && ! isStarted)
if (isRunning && callback != callback_)
{
if (callback != 0)
callback->audioDeviceAboutToStart (this);
if (callback_ != 0)
callback_->audioDeviceAboutToStart (this);

isStarted = true;
internal->start (callback);
callbackLock.enter();
callback = callback_;
callbackLock.exit();
}
}

void stop()
{
if (isStarted && internal != 0)
if (isRunning)
{
AudioIODeviceCallback* const lastCallback = internal->callback;
isStarted = false;
internal->stop (true);
callbackLock.enter();
AudioIODeviceCallback* const lastCallback = callback;
callback = 0;
callbackLock.exit();

if (lastCallback != 0)
lastCallback->audioDeviceStopped();
@@ -261345,10 +261423,7 @@ public:

bool isPlaying()
{
if (internal->callback == 0)
isStarted = false;

return isStarted;
return isRunning && callback != 0;
}

const String getLastError()
@@ -261356,36 +261431,286 @@ public:
return lastError;
}

int inputIndex, outputIndex;

juce_UseDebuggingNewOperator

private:
CoreAudioInternal* internal;
bool isOpen_, isStarted;

CriticalSection callbackLock;
Float64 sampleRate;
int numInputChannels, numOutputChannels;
int preferredBufferSize;
int actualBufferSize;
bool isRunning;
String lastError;

static OSStatus hardwareListenerProc (AudioDeviceID /*inDevice*/, UInt32 /*inLine*/, const AudioObjectPropertyAddress* pa, void* inClientData)
AudioStreamBasicDescription format;
AudioUnit audioUnit;
UInt32 audioInputIsAvailable;
AudioIODeviceCallback* callback;
BitArray activeOutputChans, activeInputChans;

AudioSampleBuffer floatData;
float* inputChannels[3];
float* outputChannels[3];
bool monoInputChannelNumber, monoOutputChannelNumber;

void prepareFloatBuffers()
{
CoreAudioInternal* const intern = (CoreAudioInternal*) inClientData;
floatData.setSize (numInputChannels + numOutputChannels, actualBufferSize);
zerostruct (inputChannels);
zerostruct (outputChannels);

switch (pa->mSelector)
for (int i = 0; i < numInputChannels; ++i)
inputChannels[i] = floatData.getSampleData (i);

for (int i = 0; i < numOutputChannels; ++i)
outputChannels[i] = floatData.getSampleData (i + numInputChannels);
}

OSStatus process (AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData) throw()
{
OSStatus err = noErr;

if (audioInputIsAvailable)
err = AudioUnitRender (audioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData);

const ScopedLock sl (callbackLock);

if (callback != 0)
{
case kAudioHardwarePropertyDevices:
intern->deviceDetailsChanged();
break;
if (audioInputIsAvailable && numInputChannels > 0)
{
short* shortData = (short*) ioData->mBuffers[0].mData;

case kAudioHardwarePropertyDefaultOutputDevice:
case kAudioHardwarePropertyDefaultInputDevice:
case kAudioHardwarePropertyDefaultSystemOutputDevice:
break;
if (numInputChannels >= 2)
{
for (UInt32 i = 0; i < inNumberFrames; ++i)
{
inputChannels[0][i] = *shortData++ * (1.0f / 32768.0f);
inputChannels[1][i] = *shortData++ * (1.0f / 32768.0f);
}
}
else
{
if (monoInputChannelNumber > 0)
++shortData;

for (UInt32 i = 0; i < inNumberFrames; ++i)
{
inputChannels[0][i] = *shortData++ * (1.0f / 32768.0f);
++shortData;
}
}
}
else
{
zeromem (inputChannels[0], sizeof (float) * inNumberFrames);
zeromem (inputChannels[1], sizeof (float) * inNumberFrames);
}

callback->audioDeviceIOCallback ((const float**) inputChannels, numInputChannels,
outputChannels, numOutputChannels,
(int) inNumberFrames);

short* shortData = (short*) ioData->mBuffers[0].mData;
int n = 0;

if (numOutputChannels >= 2)
{
for (UInt32 i = 0; i < inNumberFrames; ++i)
{
shortData [n++] = (short) (outputChannels[0][i] * 32767.0f);
shortData [n++] = (short) (outputChannels[1][i] * 32767.0f);
}
}
else if (numOutputChannels == 1)
{
for (UInt32 i = 0; i < inNumberFrames; ++i)
{
const short s = (short) (outputChannels[monoOutputChannelNumber][i] * 32767.0f);
shortData [n++] = s;
shortData [n++] = s;
}
}
else
{
zeromem (ioData->mBuffers[0].mData, 2 * sizeof (short) * inNumberFrames);
}
}
else
{
zeromem (ioData->mBuffers[0].mData, 2 * sizeof (short) * inNumberFrames);
}

return noErr;
return err;
}

CoreAudioIODevice (const CoreAudioIODevice&);
const CoreAudioIODevice& operator= (const CoreAudioIODevice&);
void updateDeviceInfo() throw()
{
UInt32 size = sizeof (sampleRate);
AudioSessionGetProperty (kAudioSessionProperty_CurrentHardwareSampleRate, &size, &sampleRate);

size = sizeof (audioInputIsAvailable);
AudioSessionGetProperty (kAudioSessionProperty_AudioInputAvailable, &size, &audioInputIsAvailable);
}

void propertyChanged (AudioSessionPropertyID inID, UInt32 inDataSize, const void* inPropertyValue)
{
if (! isRunning)
return;

if (inPropertyValue != 0)
{
CFDictionaryRef routeChangeDictionary = (CFDictionaryRef) inPropertyValue;
CFNumberRef routeChangeReasonRef = (CFNumberRef) CFDictionaryGetValue (routeChangeDictionary,
CFSTR (kAudioSession_AudioRouteChangeKey_Reason));

SInt32 routeChangeReason;
CFNumberGetValue (routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason);

if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable)
fixAudioRouteIfSetToReceiver();
}

updateDeviceInfo();
createAudioUnit();

AudioSessionSetActive (true);

if (audioUnit != 0)
{
UInt32 formatSize = sizeof (format);
AudioUnitGetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &format, &formatSize);

Float32 bufferDuration = preferredBufferSize / sampleRate;
UInt32 bufferDurationSize = sizeof (bufferDuration);
AudioSessionGetProperty (kAudioSessionProperty_CurrentHardwareIOBufferDuration, &bufferDurationSize, &bufferDurationSize);
actualBufferSize = (int) (sampleRate * bufferDuration + 0.5);

AudioOutputUnitStart (audioUnit);
}
}

void interruptionListener (UInt32 inInterruption)
{
if (inInterruption == kAudioSessionBeginInterruption)
{
isRunning = false;
AudioOutputUnitStop (audioUnit);

if (juce_iPhoneShowModalAlert ("Audio Interrupted",
"This could have been interrupted by another application or by unplugging a headset",
@"Resume",
@"Cancel"))
{
isRunning = true;
propertyChanged (0, 0, 0);
}
}

if (inInterruption == kAudioSessionEndInterruption)
{
isRunning = true;
AudioSessionSetActive (true);
AudioOutputUnitStart (audioUnit);
}
}

static OSStatus processStatic (void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData)
{
return ((IPhoneAudioIODevice*) inRefCon)->process (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
}

static void propertyChangedStatic (void* inClientData, AudioSessionPropertyID inID, UInt32 inDataSize, const void* inPropertyValue)
{
((IPhoneAudioIODevice*) inClientData)->propertyChanged (inID, inDataSize, inPropertyValue);
}

static void interruptionListenerStatic (void* inClientData, UInt32 inInterruption)
{
((IPhoneAudioIODevice*) inClientData)->interruptionListener (inInterruption);
}

void resetFormat (const int numChannels)
{
memset (&format, 0, sizeof (format));
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
format.mBitsPerChannel = 8 * sizeof (short);
format.mChannelsPerFrame = 2;
format.mFramesPerPacket = 1;
format.mBytesPerFrame = format.mBytesPerPacket = 2 * sizeof (short);
}

bool createAudioUnit()
{
if (audioUnit != 0)
{
AudioComponentInstanceDispose (audioUnit);
audioUnit = 0;
}

resetFormat (2);

AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;

AudioComponent comp = AudioComponentFindNext (0, &desc);
AudioComponentInstanceNew (comp, &audioUnit);

if (audioUnit == 0)
return false;

const UInt32 one = 1;
AudioUnitSetProperty (audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &one, sizeof (one));

AudioChannelLayout layout;
layout.mChannelBitmap = 0;
layout.mNumberChannelDescriptions = 0;
layout.mChannelLayoutTag = kAudioChannelLayoutTag_StereoHeadphones;
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input, 0, &layout, sizeof (layout));
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, 0, &layout, sizeof (layout));

AURenderCallbackStruct inputProc;
inputProc.inputProc = processStatic;
inputProc.inputProcRefCon = this;
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &inputProc, sizeof (inputProc));

AudioUnitSetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &format, sizeof (format));
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &format, sizeof (format));

AudioUnitInitialize (audioUnit);
return true;
}

// If the routing is set to go through the receiver (i.e. the speaker, but quiet), this re-routes it
// to make it loud. Needed because by default when using an input + output, the output is kept quiet.
static void fixAudioRouteIfSetToReceiver() throw()
{
CFStringRef audioRoute = 0;
UInt32 propertySize = sizeof (audioRoute);
if (AudioSessionGetProperty (kAudioSessionProperty_AudioRoute, &propertySize, &audioRoute) == noErr)
{
NSString* route = (NSString*) audioRoute;

//printf ("audio route: %s\n", [route cString]);

if ([route hasPrefix: @"Receiver"])
{
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof (audioRouteOverride), &audioRouteOverride);
}

CFRelease (audioRoute);
}
}

IPhoneAudioIODevice (const IPhoneAudioIODevice&);
const IPhoneAudioIODevice& operator= (const IPhoneAudioIODevice&);
};

class IPhoneAudioIODeviceType : public AudioIODeviceType
@@ -261393,8 +261718,7 @@ class IPhoneAudioIODeviceType : public AudioIODeviceType
public:

IPhoneAudioIODeviceType()
: AudioIODeviceType (T("iPhone Audio")),
hasScanned (false)
: AudioIODeviceType (T("iPhone Audio"))
{
}

@@ -261409,6 +261733,7 @@ public:
const StringArray getDeviceNames (const bool wantInputNames) const
{
StringArray s;
s.add (wantInputNames ? "Microphone" : "Speaker");
return s;
}

@@ -261419,20 +261744,19 @@ public:

int getIndexOfDevice (AudioIODevice* device, const bool asInput) const
{
return 0;
return device != 0 ? 0 : -1;
}

bool hasSeparateInputsAndOutputs() const { return true; }
bool hasSeparateInputsAndOutputs() const { return false; }

AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
{
if (outputDeviceName.isNotEmpty() && inputDeviceName.isNotEmpty())
return new CoreAudioIODevice (deviceName,
inputIds [inputIndex],
inputIndex,
outputIds [outputIndex],
outputIndex);
if (outputDeviceName.isNotEmpty() || inputDeviceName.isNotEmpty())
{
return new IPhoneAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName
: inputDeviceName);
}

return 0;
}


+ 6
- 2
juce_amalgamated.h View File

@@ -39225,7 +39225,7 @@ private:
#define __JUCE_GLYPHARRANGEMENT_JUCEHEADER__

/**
An glyph from a particular font, with a particular size, style,
A glyph from a particular font, with a particular size, style,
typeface and position.

@see GlyphArrangement, Font
@@ -47015,6 +47015,10 @@ public:
*/
virtual int getColumnAutoSizeWidth (int columnId);

/** Returns a tooltip for a particular cell in the table.
*/
virtual const String getCellTooltip (int rowNumber, int columnId);

/** Override this to be informed when rows are selected or deselected.

@see ListBox::selectedRowsChanged()
@@ -53668,7 +53672,7 @@ private:
/********* End of inlined file: juce_ActiveXControlComponent.h *********/

typedef ActiveXControlComponent QTCompBaseClass;
#else
#elif JUCE_MAC

typedef NSViewComponent QTCompBaseClass;
#endif


+ 15
- 1
src/gui/components/controls/juce_TableListBox.cpp View File

@@ -38,7 +38,8 @@ BEGIN_JUCE_NAMESPACE
//==============================================================================
static const tchar* const tableColumnPropertyTag = T("_tableColumnID");
class TableListRowComp : public Component
class TableListRowComp : public Component,
public TooltipClient
{
public:
TableListRowComp (TableListBox& owner_)
@@ -242,6 +243,19 @@ public:
owner.getModel()->cellDoubleClicked (row, columnId, e);
}
const String getTooltip()
{
int x, y;
getMouseXYRelative (x, y);
const int columnId = owner.getHeader()->getColumnIdAtX (x);
if (columnId != 0 && owner.getModel() != 0)
return owner.getModel()->getCellTooltip (row, columnId);
return String::empty;
}
juce_UseDebuggingNewOperator
private:


+ 4
- 0
src/gui/components/controls/juce_TableListBox.h View File

@@ -144,6 +144,10 @@ public:
*/
virtual int getColumnAutoSizeWidth (int columnId);
/** Returns a tooltip for a particular cell in the table.
*/
virtual const String getCellTooltip (int rowNumber, int columnId);
//==============================================================================
/** Override this to be informed when rows are selected or deselected.


+ 2
- 2
src/gui/components/controls/juce_TreeView.cpp View File

@@ -233,8 +233,8 @@ public:
comp->setBounds (pos);
}
}
if ((! keep)
if ((! keep)
&& Component::isMouseButtonDownAnywhere()
&& (comp == Component::getComponentUnderMouse()
|| comp->isParentOf (Component::getComponentUnderMouse())))


+ 1
- 1
src/gui/components/menus/juce_MenuBarComponent.cpp View File

@@ -225,7 +225,7 @@ void MenuBarComponent::showMenu (int index)
if (m.lookAndFeel == 0)
m.setLookAndFeel (&getLookAndFeel());
currentPopup = m.createMenuComponent (x, getScreenY(),
w, getHeight(),
0, w, 0, 0,


+ 1
- 1
src/gui/components/special/juce_QuickTimeMovieComponent.h View File

@@ -33,7 +33,7 @@
#if JUCE_WINDOWS
#include "juce_ActiveXControlComponent.h"
typedef ActiveXControlComponent QTCompBaseClass;
#else
#elif JUCE_MAC
#include "juce_NSViewComponent.h"
typedef NSViewComponent QTCompBaseClass;
#endif


+ 1
- 1
src/gui/graphics/fonts/juce_GlyphArrangement.h View File

@@ -32,7 +32,7 @@
//==============================================================================
/**
An glyph from a particular font, with a particular size, style,
A glyph from a particular font, with a particular size, style,
typeface and position.
@see GlyphArrangement, Font


+ 372
- 104
src/native/mac/juce_iphone_Audio.cpp View File

@@ -28,39 +28,44 @@
#if JUCE_INCLUDED_FILE
class IPhoneAudioIODevice : public AudioIODeviceType
//==================================================================================================
class IPhoneAudioIODevice : public AudioIODevice
{
public:
//==============================================================================
IPhoneAudioIODevice (const String& deviceName, const bool isInput_)
IPhoneAudioIODevice (const String& deviceName)
: AudioIODevice (deviceName, T("Audio")),
isInput (isInput_),
isOpen_ (false),
isStarted (false)
audioUnit (0),
isRunning (false),
callback (0),
actualBufferSize (0),
floatData (1, 2)
{
numInputChannels = 2;
numOutputChannels = 2;
preferredBufferSize = 0;
AudioSessionInitialize (0, 0, interruptionListenerStatic, this);
updateDeviceInfo();
}
~IPhoneAudioIODeviceType()
~IPhoneAudioIODevice()
{
close();
}
const StringArray getOutputChannelNames()
{
StringArray s;
if (! isInput)
{
s.add ("Left");
s.add ("Right");
}
s.add ("Left");
s.add ("Right");
return s;
}
const StringArray getInputChannelNames()
{
StringArray s;
if (isInput)
if (audioInputIsAvailable)
{
s.add ("Left");
s.add ("Right");
@@ -70,137 +75,150 @@ public:
int getNumSampleRates()
{
return sampleRates.size();
return 1;
}
double getSampleRate (int index)
{
return sampleRates [index];
return sampleRate;
}
int getNumBufferSizesAvailable()
{
return bufferSizes.size();
return 1;
}
int getBufferSizeSamples (int index)
{
return bufferSizes [index];
return getDefaultBufferSize();
}
int getDefaultBufferSize()
{
for (int i = 0; i < getNumBufferSizesAvailable(); ++i)
if (getBufferSizeSamples(i) >= 512)
return getBufferSizeSamples(i);
return 512;
return 1024;
}
const String open (const BitArray& inputChannels,
const BitArray& outputChannels,
double sampleRate,
int bufferSizeSamples)
int bufferSize)
{
isOpen_ = true;
if (bufferSizeSamples <= 0)
bufferSizeSamples = getDefaultBufferSize();
close();
lastError = String::empty;
preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize;
// xxx set up channel mapping
activeOutputChans = outputChannels;
activeOutputChans.setRange (2, activeOutputChans.getHighestBit(), false);
numOutputChannels = activeOutputChans.countNumberOfSetBits();
monoOutputChannelNumber = activeOutputChans.findNextSetBit (0);
activeInputChans = inputChannels;
activeInputChans.setRange (2, activeInputChans.getHighestBit(), false);
numInputChannels = activeInputChans.countNumberOfSetBits();
monoInputChannelNumber = activeInputChans.findNextSetBit (0);
AudioSessionSetActive (true);
UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord;
AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof (audioCategory), &audioCategory);
AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange, propertyChangedStatic, this);
fixAudioRouteIfSetToReceiver();
updateDeviceInfo();
isOpen_ = lastError.isEmpty();
Float32 bufferDuration = preferredBufferSize / sampleRate;
AudioSessionSetProperty (kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof (bufferDuration), &bufferDuration);
actualBufferSize = preferredBufferSize;
prepareFloatBuffers();
isRunning = true;
propertyChanged (0, 0, 0); // creates and starts the AU
lastError = audioUnit != 0 ? String::empty
: T("Couldn't open the device");
return lastError;
}
void close()
{
isOpen_ = false;
if (isRunning)
{
isRunning = false;
AudioSessionSetActive (false);
if (audioUnit != 0)
{
AudioComponentInstanceDispose (audioUnit);
audioUnit = 0;
}
}
}
bool isOpen()
{
return isOpen_;
return isRunning;
}
int getCurrentBufferSizeSamples()
{
return internal != 0 ? internal->getBufferSize() : 512;
return actualBufferSize;
}
double getCurrentSampleRate()
{
return internal != 0 ? internal->getSampleRate() : 0;
return sampleRate;
}
int getCurrentBitDepth()
{
return 32; // no way to find out, so just assume it's high..
return 16;
}
const BitArray getActiveOutputChannels() const
{
return internal != 0 ? internal->activeOutputChans : BitArray();
return activeOutputChans;
}
const BitArray getActiveInputChannels() const
{
BitArray chans;
if (internal != 0)
{
chans = internal->activeInputChans;
if (internal->inputDevice != 0)
chans.orWith (internal->inputDevice->activeInputChans);
}
return chans;
return activeInputChans;
}
int getOutputLatencyInSamples()
{
if (internal == 0)
return 0;
// this seems like a good guess at getting the latency right - comparing
// this with a round-trip measurement, it gets it to within a few millisecs
// for the built-in mac soundcard
return internal->outputLatency + internal->getBufferSize() * 2;
return 0; //xxx
}
int getInputLatencyInSamples()
{
if (internal == 0)
return 0;
return internal->inputLatency + internal->getBufferSize() * 2;
return 0; //xxx
}
void start (AudioIODeviceCallback* callback)
void start (AudioIODeviceCallback* callback_)
{
if (internal != 0 && ! isStarted)
if (isRunning && callback != callback_)
{
if (callback != 0)
callback->audioDeviceAboutToStart (this);
if (callback_ != 0)
callback_->audioDeviceAboutToStart (this);
isStarted = true;
internal->start (callback);
callbackLock.enter();
callback = callback_;
callbackLock.exit();
}
}
void stop()
{
if (isStarted && internal != 0)
if (isRunning)
{
AudioIODeviceCallback* const lastCallback = internal->callback;
isStarted = false;
internal->stop (true);
callbackLock.enter();
AudioIODeviceCallback* const lastCallback = callback;
callback = 0;
callbackLock.exit();
if (lastCallback != 0)
lastCallback->audioDeviceStopped();
@@ -209,10 +227,7 @@ public:
bool isPlaying()
{
if (internal->callback == 0)
isStarted = false;
return isStarted;
return isRunning && callback != 0;
}
const String getLastError()
@@ -220,36 +235,290 @@ public:
return lastError;
}
int inputIndex, outputIndex;
juce_UseDebuggingNewOperator
private:
CoreAudioInternal* internal;
bool isOpen_, isStarted;
//==================================================================================================
CriticalSection callbackLock;
Float64 sampleRate;
int numInputChannels, numOutputChannels;
int preferredBufferSize;
int actualBufferSize;
bool isRunning;
String lastError;
static OSStatus hardwareListenerProc (AudioDeviceID /*inDevice*/, UInt32 /*inLine*/, const AudioObjectPropertyAddress* pa, void* inClientData)
AudioStreamBasicDescription format;
AudioUnit audioUnit;
UInt32 audioInputIsAvailable;
AudioIODeviceCallback* callback;
BitArray activeOutputChans, activeInputChans;
AudioSampleBuffer floatData;
float* inputChannels[3];
float* outputChannels[3];
bool monoInputChannelNumber, monoOutputChannelNumber;
void prepareFloatBuffers()
{
CoreAudioInternal* const intern = (CoreAudioInternal*) inClientData;
floatData.setSize (numInputChannels + numOutputChannels, actualBufferSize);
zerostruct (inputChannels);
zerostruct (outputChannels);
for (int i = 0; i < numInputChannels; ++i)
inputChannels[i] = floatData.getSampleData (i);
for (int i = 0; i < numOutputChannels; ++i)
outputChannels[i] = floatData.getSampleData (i + numInputChannels);
}
//==================================================================================================
OSStatus process (AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData) throw()
{
OSStatus err = noErr;
if (audioInputIsAvailable)
err = AudioUnitRender (audioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData);
const ScopedLock sl (callbackLock);
switch (pa->mSelector)
if (callback != 0)
{
case kAudioHardwarePropertyDevices:
intern->deviceDetailsChanged();
break;
case kAudioHardwarePropertyDefaultOutputDevice:
case kAudioHardwarePropertyDefaultInputDevice:
case kAudioHardwarePropertyDefaultSystemOutputDevice:
break;
if (audioInputIsAvailable && numInputChannels > 0)
{
short* shortData = (short*) ioData->mBuffers[0].mData;
if (numInputChannels >= 2)
{
for (UInt32 i = 0; i < inNumberFrames; ++i)
{
inputChannels[0][i] = *shortData++ * (1.0f / 32768.0f);
inputChannels[1][i] = *shortData++ * (1.0f / 32768.0f);
}
}
else
{
if (monoInputChannelNumber > 0)
++shortData;
for (UInt32 i = 0; i < inNumberFrames; ++i)
{
inputChannels[0][i] = *shortData++ * (1.0f / 32768.0f);
++shortData;
}
}
}
else
{
zeromem (inputChannels[0], sizeof (float) * inNumberFrames);
zeromem (inputChannels[1], sizeof (float) * inNumberFrames);
}
callback->audioDeviceIOCallback ((const float**) inputChannels, numInputChannels,
outputChannels, numOutputChannels,
(int) inNumberFrames);
short* shortData = (short*) ioData->mBuffers[0].mData;
int n = 0;
if (numOutputChannels >= 2)
{
for (UInt32 i = 0; i < inNumberFrames; ++i)
{
shortData [n++] = (short) (outputChannels[0][i] * 32767.0f);
shortData [n++] = (short) (outputChannels[1][i] * 32767.0f);
}
}
else if (numOutputChannels == 1)
{
for (UInt32 i = 0; i < inNumberFrames; ++i)
{
const short s = (short) (outputChannels[monoOutputChannelNumber][i] * 32767.0f);
shortData [n++] = s;
shortData [n++] = s;
}
}
else
{
zeromem (ioData->mBuffers[0].mData, 2 * sizeof (short) * inNumberFrames);
}
}
else
{
zeromem (ioData->mBuffers[0].mData, 2 * sizeof (short) * inNumberFrames);
}
return noErr;
return err;
}
CoreAudioIODevice (const CoreAudioIODevice&);
const CoreAudioIODevice& operator= (const CoreAudioIODevice&);
void updateDeviceInfo() throw()
{
UInt32 size = sizeof (sampleRate);
AudioSessionGetProperty (kAudioSessionProperty_CurrentHardwareSampleRate, &size, &sampleRate);
size = sizeof (audioInputIsAvailable);
AudioSessionGetProperty (kAudioSessionProperty_AudioInputAvailable, &size, &audioInputIsAvailable);
}
void propertyChanged (AudioSessionPropertyID inID, UInt32 inDataSize, const void* inPropertyValue)
{
if (! isRunning)
return;
if (inPropertyValue != 0)
{
CFDictionaryRef routeChangeDictionary = (CFDictionaryRef) inPropertyValue;
CFNumberRef routeChangeReasonRef = (CFNumberRef) CFDictionaryGetValue (routeChangeDictionary,
CFSTR (kAudioSession_AudioRouteChangeKey_Reason));
SInt32 routeChangeReason;
CFNumberGetValue (routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason);
if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable)
fixAudioRouteIfSetToReceiver();
}
updateDeviceInfo();
createAudioUnit();
AudioSessionSetActive (true);
if (audioUnit != 0)
{
UInt32 formatSize = sizeof (format);
AudioUnitGetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &format, &formatSize);
Float32 bufferDuration = preferredBufferSize / sampleRate;
UInt32 bufferDurationSize = sizeof (bufferDuration);
AudioSessionGetProperty (kAudioSessionProperty_CurrentHardwareIOBufferDuration, &bufferDurationSize, &bufferDurationSize);
actualBufferSize = (int) (sampleRate * bufferDuration + 0.5);
AudioOutputUnitStart (audioUnit);
}
}
void interruptionListener (UInt32 inInterruption)
{
if (inInterruption == kAudioSessionBeginInterruption)
{
isRunning = false;
AudioOutputUnitStop (audioUnit);
if (juce_iPhoneShowModalAlert ("Audio Interrupted",
"This could have been interrupted by another application or by unplugging a headset",
@"Resume",
@"Cancel"))
{
isRunning = true;
propertyChanged (0, 0, 0);
}
}
if (inInterruption == kAudioSessionEndInterruption)
{
isRunning = true;
AudioSessionSetActive (true);
AudioOutputUnitStart (audioUnit);
}
}
//==================================================================================================
static OSStatus processStatic (void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData)
{
return ((IPhoneAudioIODevice*) inRefCon)->process (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
}
static void propertyChangedStatic (void* inClientData, AudioSessionPropertyID inID, UInt32 inDataSize, const void* inPropertyValue)
{
((IPhoneAudioIODevice*) inClientData)->propertyChanged (inID, inDataSize, inPropertyValue);
}
static void interruptionListenerStatic (void* inClientData, UInt32 inInterruption)
{
((IPhoneAudioIODevice*) inClientData)->interruptionListener (inInterruption);
}
//==================================================================================================
void resetFormat (const int numChannels)
{
memset (&format, 0, sizeof (format));
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
format.mBitsPerChannel = 8 * sizeof (short);
format.mChannelsPerFrame = 2;
format.mFramesPerPacket = 1;
format.mBytesPerFrame = format.mBytesPerPacket = 2 * sizeof (short);
}
bool createAudioUnit()
{
if (audioUnit != 0)
{
AudioComponentInstanceDispose (audioUnit);
audioUnit = 0;
}
resetFormat (2);
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
AudioComponent comp = AudioComponentFindNext (0, &desc);
AudioComponentInstanceNew (comp, &audioUnit);
if (audioUnit == 0)
return false;
const UInt32 one = 1;
AudioUnitSetProperty (audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &one, sizeof (one));
AudioChannelLayout layout;
layout.mChannelBitmap = 0;
layout.mNumberChannelDescriptions = 0;
layout.mChannelLayoutTag = kAudioChannelLayoutTag_StereoHeadphones;
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input, 0, &layout, sizeof (layout));
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, 0, &layout, sizeof (layout));
AURenderCallbackStruct inputProc;
inputProc.inputProc = processStatic;
inputProc.inputProcRefCon = this;
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &inputProc, sizeof (inputProc));
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &format, sizeof (format));
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &format, sizeof (format));
AudioUnitInitialize (audioUnit);
return true;
}
// If the routing is set to go through the receiver (i.e. the speaker, but quiet), this re-routes it
// to make it loud. Needed because by default when using an input + output, the output is kept quiet.
static void fixAudioRouteIfSetToReceiver() throw()
{
CFStringRef audioRoute = 0;
UInt32 propertySize = sizeof (audioRoute);
if (AudioSessionGetProperty (kAudioSessionProperty_AudioRoute, &propertySize, &audioRoute) == noErr)
{
NSString* route = (NSString*) audioRoute;
//printf ("audio route: %s\n", [route cString]);
if ([route hasPrefix: @"Receiver"])
{
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof (audioRouteOverride), &audioRouteOverride);
}
CFRelease (audioRoute);
}
}
IPhoneAudioIODevice (const IPhoneAudioIODevice&);
const IPhoneAudioIODevice& operator= (const IPhoneAudioIODevice&);
};
@@ -259,8 +528,7 @@ class IPhoneAudioIODeviceType : public AudioIODeviceType
public:
//==============================================================================
IPhoneAudioIODeviceType()
: AudioIODeviceType (T("iPhone Audio")),
hasScanned (false)
: AudioIODeviceType (T("iPhone Audio"))
{
}
@@ -276,6 +544,7 @@ public:
const StringArray getDeviceNames (const bool wantInputNames) const
{
StringArray s;
s.add (wantInputNames ? "Microphone" : "Speaker");
return s;
}
@@ -286,20 +555,19 @@ public:
int getIndexOfDevice (AudioIODevice* device, const bool asInput) const
{
return 0;
return device != 0 ? 0 : -1;
}
bool hasSeparateInputsAndOutputs() const { return true; }
bool hasSeparateInputsAndOutputs() const { return false; }
AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
{
if (outputDeviceName.isNotEmpty() && inputDeviceName.isNotEmpty())
return new CoreAudioIODevice (deviceName,
inputIds [inputIndex],
inputIndex,
outputIds [outputIndex],
outputIndex);
if (outputDeviceName.isNotEmpty() || inputDeviceName.isNotEmpty())
{
return new IPhoneAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName
: inputDeviceName);
}
return 0;
}


+ 56
- 13
src/native/mac/juce_iphone_MiscUtilities.mm View File

@@ -95,34 +95,77 @@ void PlatformUtilities::addItemToDock (const File& file)
//==============================================================================
#if ! JUCE_ONLY_BUILD_CORE_LIBRARY
bool AlertWindow::showNativeDialogBox (const String& title,
const String& bodyText,
bool isOkCancel)
END_JUCE_NAMESPACE
@interface JuceAlertBoxDelegate : NSObject
{
@public
bool clickedOk;
}
- (void) alertView: (UIAlertView*) alertView clickedButtonAtIndex: (NSInteger) buttonIndex;
@end
@implementation JuceAlertBoxDelegate
- (void) alertView: (UIAlertView*) alertView clickedButtonAtIndex: (NSInteger) buttonIndex
{
clickedOk = (buttonIndex == 0);
alertView.hidden = true;
}
@end
BEGIN_JUCE_NAMESPACE
// (This function is used directly by other bits of code)
bool juce_iPhoneShowModalAlert (const String& title,
const String& bodyText,
NSString* okButtonText,
NSString* cancelButtonText)
{
const ScopedAutoReleasePool pool;
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle: juceStringToNS (title)
message: juceStringToNS (title)
delegate: nil
cancelButtonTitle: @"OK"
otherButtonTitles: (isOkCancel ? @"Cancel" : nil), nil] autorelease];
alert.cancelButtonIndex = alert.firstOtherButtonIndex;
JuceAlertBoxDelegate* callback = [[JuceAlertBoxDelegate alloc] init];
UIAlertView* alert = [[UIAlertView alloc] initWithTitle: juceStringToNS (title)
message: juceStringToNS (bodyText)
delegate: callback
cancelButtonTitle: okButtonText
otherButtonTitles: cancelButtonText, nil];
[alert retain];
[alert show];
// xxx need to use a delegate to find which button was clicked
return false;
while (! alert.hidden && alert.superview != nil)
[[NSRunLoop mainRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
const bool result = callback->clickedOk;
[alert release];
[callback release];
return result;
}
bool AlertWindow::showNativeDialogBox (const String& title,
const String& bodyText,
bool isOkCancel)
{
return juce_iPhoneShowModalAlert (title, bodyText,
@"OK",
isOkCancel ? @"Cancel" : nil);
}
//==============================================================================
bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& files, const bool canMoveFiles)
{
jassertfalse // not implemented!
jassertfalse // no such thing on the iphone!
return false;
}
bool DragAndDropContainer::performExternalDragDropOfText (const String& text)
{
jassertfalse // not implemented!
jassertfalse // no such thing on the iphone!
return false;
}


+ 0
- 2
src/native/mac/juce_mac_NativeIncludes.h View File

@@ -74,8 +74,6 @@
#if MACOS_10_4_OR_EARLIER
#include <GLUT/glut.h>
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
#endif // __JUCE_MAC_NATIVEINCLUDES_JUCEHEADER__

+ 3
- 2
src/native/windows/juce_win32_ASIO.cpp View File

@@ -1816,11 +1816,12 @@ public:
AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
{
// ASIO can't open two different devices for input and output - they must be the same one.
jassert (inputDeviceName == outputDeviceName || outputDeviceName.isEmpty() || inputDeviceName.isEmpty());
(void) inputDeviceName;
jassert (hasScanned); // need to call scanForDevices() before doing this
const int index = deviceNames.indexOf (outputDeviceName);
const int index = deviceNames.indexOf (outputDeviceName.isNotEmpty() ? outputDeviceName
: inputDeviceName);
if (index >= 0)
{


Loading…
Cancel
Save