| @@ -4,10 +4,12 @@ | |||
| package="com.juce.jucedemoplugin"> | |||
| <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"/> | |||
| <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="23"/> | |||
| <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> | |||
| <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> | |||
| <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> | |||
| <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> | |||
| <uses-permission android:name="android.permission.BLUETOOTH"/> | |||
| <uses-permission android:name="android.permission.INTERNET"/> | |||
| <uses-permission android:name="android.permission.RECORD_AUDIO"/> | |||
| <application android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar" android:hardwareAccelerated="false"> | |||
| <activity android:name="JuceDemoPlugin" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize" | |||
| android:screenOrientation="landscape"> | |||
| @@ -129,7 +129,7 @@ | |||
| </XCODE_IPHONE> | |||
| <ANDROIDSTUDIO targetFolder="Builds/Android" androidSDKPath="" androidNDKPath="" | |||
| androidTheme="@android:style/Theme.NoTitleBar" androidScreenOrientation="landscape" | |||
| androidMinimumSDK="23"> | |||
| androidMinimumSDK="23" microphonePermissionNeeded="1" androidInternetNeeded="0"> | |||
| <CONFIGURATIONS> | |||
| <CONFIGURATION name="Debug" androidArchitectures="armeabi x86" isDebug="1" optimisation="1" | |||
| targetName="JuceDemoPlugin"/> | |||
| @@ -193,9 +193,10 @@ bool JuceDemoPluginAudioProcessor::isBusesLayoutSupported (const BusesLayout& la | |||
| { | |||
| // Only mono/stereo and input/output must have same layout | |||
| const AudioChannelSet& mainOutput = layouts.getMainOutputChannelSet(); | |||
| const AudioChannelSet& mainInput = layouts.getMainInputChannelSet(); | |||
| // input and output layout must be the same | |||
| if (layouts.getMainInputChannelSet() != mainOutput) | |||
| // input and output layout must either be the same or the input must be disabled altogether | |||
| if (! mainInput.isDisabled() && mainInput != mainOutput) | |||
| return false; | |||
| // do not allow disabling the main buses | |||
| @@ -62,14 +62,31 @@ public: | |||
| bool takeOwnershipOfSettings = true, | |||
| const String& preferredDefaultDeviceName = String(), | |||
| const AudioDeviceManager::AudioDeviceSetup* preferredSetupOptions = nullptr, | |||
| const Array<PluginInOuts>& constrainToConfiguration = Array<PluginInOuts>()) | |||
| const Array<PluginInOuts>& channels = Array<PluginInOuts>()) | |||
| : settings (settingsToUse, takeOwnershipOfSettings), | |||
| channelConfiguration (constrainToConfiguration), | |||
| channelConfiguration (channels), | |||
| shouldMuteInput (! isInterAppAudioConnected()) | |||
| { | |||
| createPlugin(); | |||
| setupAudioDevices (preferredDefaultDeviceName, preferredSetupOptions); | |||
| auto inChannels = (channelConfiguration.size() > 0 ? channelConfiguration[0].numIns | |||
| : processor->getMainBusNumInputChannels()); | |||
| if (preferredSetupOptions != nullptr) | |||
| options = new AudioDeviceManager::AudioDeviceSetup (*preferredSetupOptions); | |||
| if (inChannels > 0 && RuntimePermissions::isRequired (RuntimePermissions::recordAudio) | |||
| && ! RuntimePermissions::isGranted (RuntimePermissions::recordAudio)) | |||
| RuntimePermissions::request (RuntimePermissions::recordAudio, | |||
| [this, preferredDefaultDeviceName] (bool granted) { init (granted, preferredDefaultDeviceName); }); | |||
| else | |||
| init (true, preferredDefaultDeviceName); | |||
| } | |||
| void init (bool enableAudioInput, const String& preferredDefaultDeviceName) | |||
| { | |||
| setupAudioDevices (enableAudioInput, preferredDefaultDeviceName, options); | |||
| reloadPluginState(); | |||
| startPlaying(); | |||
| @@ -263,7 +280,8 @@ public: | |||
| } | |||
| } | |||
| void reloadAudioDeviceState (const String& preferredDefaultDeviceName, | |||
| void reloadAudioDeviceState (bool enableAudioInput, | |||
| const String& preferredDefaultDeviceName, | |||
| const AudioDeviceManager::AudioDeviceSetup* preferredSetupOptions) | |||
| { | |||
| ScopedPointer<XmlElement> savedState; | |||
| @@ -287,7 +305,7 @@ public: | |||
| totalOutChannels = defaultConfig.numOuts; | |||
| } | |||
| deviceManager.initialise (totalInChannels, | |||
| deviceManager.initialise (enableAudioInput ? totalInChannels : 0, | |||
| totalOutChannels, | |||
| savedState, | |||
| true, | |||
| @@ -365,6 +383,8 @@ public: | |||
| Value shouldMuteInput; | |||
| AudioSampleBuffer emptyBuffer; | |||
| ScopedPointer<AudioDeviceManager::AudioDeviceSetup> options; | |||
| #if JUCE_IOS || JUCE_ANDROID | |||
| StringArray lastMidiDevices; | |||
| #endif | |||
| @@ -476,13 +496,14 @@ private: | |||
| } | |||
| //============================================================================== | |||
| void setupAudioDevices (const String& preferredDefaultDeviceName, | |||
| void setupAudioDevices (bool enableAudioInput, | |||
| const String& preferredDefaultDeviceName, | |||
| const AudioDeviceManager::AudioDeviceSetup* preferredSetupOptions) | |||
| { | |||
| deviceManager.addAudioCallback (this); | |||
| deviceManager.addMidiInputCallback ({}, &player); | |||
| reloadAudioDeviceState (preferredDefaultDeviceName, preferredSetupOptions); | |||
| reloadAudioDeviceState (enableAudioInput, preferredDefaultDeviceName, preferredSetupOptions); | |||
| } | |||
| void shutDownAudioDevices() | |||
| @@ -84,10 +84,6 @@ public: | |||
| */ | |||
| #ifdef DOXYGEN | |||
| #define START_JUCE_APPLICATION(AppClass) | |||
| #elif JUCE_ANDROID | |||
| #define START_JUCE_APPLICATION(AppClass) \ | |||
| juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } | |||
| #else | |||
| #if JUCE_WINDOWS && ! defined (_CONSOLE) | |||
| #define JUCE_MAIN_FUNCTION int __stdcall WinMain (struct HINSTANCE__*, struct HINSTANCE__*, char*, int) | |||
| @@ -115,6 +111,13 @@ public: | |||
| return juce::JUCEApplicationBase::main (JUCE_MAIN_FUNCTION_ARGS); \ | |||
| } | |||
| #elif JUCE_ANDROID | |||
| #define JUCE_CREATE_APPLICATION_DEFINE(AppClass) \ | |||
| juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } | |||
| #define JUCE_MAIN_FUNCTION_DEFINITION | |||
| #else | |||
| #define JUCE_CREATE_APPLICATION_DEFINE(AppClass) \ | |||