diff --git a/changes.txt b/changes.txt index 9df6acc12..1d74c06ce 100644 --- a/changes.txt +++ b/changes.txt @@ -113,6 +113,7 @@ Released: N/A * Fixed Shader:send and Shader:sendColor ignoring the last argument for an array. * Fixed a crash when love.graphics.pop is called after a love.window.setMode while the transformation stack was not empty. * Fixed BezierCurves to error instead of hanging in some situations. + * Fixed compilation of luasocket with newer luajit 2.1.0 beta versions. * Improved command line argument handling. * Improved seeking support, especially for short video files. diff --git a/platform/xcode/love.xcodeproj/project.pbxproj b/platform/xcode/love.xcodeproj/project.pbxproj index bc38e00b6..152003d9a 100644 --- a/platform/xcode/love.xcodeproj/project.pbxproj +++ b/platform/xcode/love.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ A9D307F2106635D3004FEDF8 /* physfs.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9D307E9106635C3004FEDF8 /* physfs.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; A9F169AC109E825000FC83D1 /* mpg123.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9F169A6109E824900FC83D1 /* mpg123.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; A9F169AD109E825000FC83D1 /* libmodplug.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9F16926109E7BAD00FC83D1 /* libmodplug.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + CE73F8001EEB64150052DAB3 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE73F7FF1EEB64150052DAB3 /* AVFoundation.framework */; }; FA0797991BF480A200034B7C /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA0797981BF480A200034B7C /* GameController.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; FA08F69616C766E000F007B5 /* love.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; }; FA08F69716C766E700F007B5 /* love.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; @@ -110,6 +111,7 @@ A9D307E9106635C3004FEDF8 /* physfs.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = physfs.framework; path = /Library/Frameworks/physfs.framework; sourceTree = ""; }; A9F16926109E7BAD00FC83D1 /* libmodplug.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = libmodplug.framework; path = /Library/Frameworks/libmodplug.framework; sourceTree = ""; }; A9F169A6109E824900FC83D1 /* mpg123.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = mpg123.framework; path = /Library/Frameworks/mpg123.framework; sourceTree = ""; }; + CE73F7FF1EEB64150052DAB3 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/AVFoundation.framework; sourceTree = DEVELOPER_DIR; }; FA0797981BF480A200034B7C /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.1.sdk/System/Library/Frameworks/GameController.framework; sourceTree = DEVELOPER_DIR; }; FA08F69116C765A200F007B5 /* love.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = love.framework; sourceTree = BUILT_PRODUCTS_DIR; }; FA0B7F061A95AAF3000E1D17 /* love.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = love.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -149,6 +151,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CE73F8001EEB64150052DAB3 /* AVFoundation.framework in Frameworks */, FA5D24D11A96E73300C6FC8F /* liblove.a in Frameworks */, FA5D24C21A96D78000C6FC8F /* Foundation.framework in Frameworks */, FA5D24961A96CAC200C6FC8F /* CoreMotion.framework in Frameworks */, @@ -169,6 +172,7 @@ 1058C7A0FEA54F0111CA2CBB /* Frameworks */ = { isa = PBXGroup; children = ( + CE73F7FF1EEB64150052DAB3 /* AVFoundation.framework */, FA5D24801A96C97900C6FC8F /* ios */, FA0B7EEC1A959249000E1D17 /* macosx */, ); diff --git a/src/common/android.cpp b/src/common/android.cpp index 7c138c864..ef684347b 100644 --- a/src/common/android.cpp +++ b/src/common/android.cpp @@ -225,6 +225,22 @@ bool createStorageDirectories() return true; } +bool hasBackgroundMusic() +{ + JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv(); + jobject activity = (jobject) SDL_AndroidGetActivity(); + + jclass clazz(env->GetObjectClass(activity)); + jmethodID method_id = env->GetMethodID(clazz, "hasBackgroundMusic", "()Z"); + + jboolean result = env->CallBooleanMethod(activity, method_id); + + env->DeleteLocalRef(activity); + env->DeleteLocalRef(clazz); + + return result; +} + } // android } // love diff --git a/src/common/android.h b/src/common/android.h index 9c6ab59be..18ce2948c 100644 --- a/src/common/android.h +++ b/src/common/android.h @@ -66,6 +66,8 @@ bool mkdir(const char *path); bool createStorageDirectories(); +bool hasBackgroundMusic(); + } // android } // love diff --git a/src/common/ios.h b/src/common/ios.h index 991205d25..fae5c652c 100644 --- a/src/common/ios.h +++ b/src/common/ios.h @@ -64,6 +64,16 @@ std::string getExecutablePath(); **/ void vibrate(); +/** + * Enable mix mode (e.g. with background music apps) and playback with a muted device. + **/ +void setAudioMixWithOthers(bool mixEnabled); + +/** + * Returns whether another application is playing audio. + **/ +bool hasBackgroundMusic(); + } // ios } // love diff --git a/src/common/ios.mm b/src/common/ios.mm index 50f498046..321a5c48f 100644 --- a/src/common/ios.mm +++ b/src/common/ios.mm @@ -26,6 +26,7 @@ #import #import +#import #include @@ -344,6 +345,28 @@ void vibrate() } } +void setAudioMixWithOthers(bool mixEnabled) +{ + @autoreleasepool + { + NSString *category = AVAudioSessionCategorySoloAmbient; + NSError *err; + + if (mixEnabled) + category = AVAudioSessionCategoryAmbient; + + if (![[AVAudioSession sharedInstance] setCategory:category error:&err]) + NSLog(@"Error in AVAudioSession setCategory: %@", [err localizedDescription]); + } +} + +bool hasBackgroundMusic() +{ + if ([[AVAudioSession sharedInstance] respondsToSelector:@selector(secondaryAudioShouldBeSilencedHint)]) + return [[AVAudioSession sharedInstance] secondaryAudioShouldBeSilencedHint]; + return false; +} + } // ios } // love diff --git a/src/modules/audio/wrap_Audio.cpp b/src/modules/audio/wrap_Audio.cpp index 2503b9f67..2c7d32902 100644 --- a/src/modules/audio/wrap_Audio.cpp +++ b/src/modules/audio/wrap_Audio.cpp @@ -25,6 +25,9 @@ #include "null/Audio.h" #include "common/runtime.h" +#ifdef LOVE_IOS +#include "common/ios.h" +#endif // C++ #include @@ -519,6 +522,17 @@ int w_isEffectsSupported(lua_State *L) return 1; } +#ifdef LOVE_IOS +int w_setMixMode(lua_State *L) +{ + love::ios::setAudioMixWithOthers(lua_toboolean(L, 1)); +#else +int w_setMixMode(lua_State *) +{ +#endif + return 0; +} + // List of functions to wrap. static const luaL_Reg functions[] = { @@ -549,6 +563,7 @@ static const luaL_Reg functions[] = { "getMaxSceneEffects", w_getMaxSceneEffects }, { "getMaxSourceEffects", w_getMaxSourceEffects }, { "isEffectsSupported", w_isEffectsSupported }, + { "setMixMode", w_setMixMode }, { 0, 0 } }; diff --git a/src/modules/system/System.cpp b/src/modules/system/System.cpp index 2c330f2fb..c8075ded0 100644 --- a/src/modules/system/System.cpp +++ b/src/modules/system/System.cpp @@ -158,6 +158,17 @@ void System::vibrate(double seconds) const #endif } +bool System::hasBackgroundMusic() const +{ +#if defined(LOVE_ANDROID) + return love::android::hasBackgroundMusic(); +#elif defined(LOVE_IOS) + return love::ios::hasBackgroundMusic(); +#else + return false; +#endif +} + bool System::getConstant(const char *in, System::PowerState &out) { return powerStates.find(in, out); diff --git a/src/modules/system/System.h b/src/modules/system/System.h index 961df27b1..a4b490b1d 100644 --- a/src/modules/system/System.h +++ b/src/modules/system/System.h @@ -106,6 +106,14 @@ public: */ virtual void vibrate(double seconds) const; + /** + * Gets if the user is playing music on background. + * Throws an exception on unsupported platforms. + * + * @return Whether a music is playing on background. + **/ + bool hasBackgroundMusic() const; + static bool getConstant(const char *in, PowerState &out); static bool getConstant(PowerState in, const char *&out); diff --git a/src/modules/system/wrap_System.cpp b/src/modules/system/wrap_System.cpp index 9e5d6ed76..07ba99b5c 100644 --- a/src/modules/system/wrap_System.cpp +++ b/src/modules/system/wrap_System.cpp @@ -95,6 +95,12 @@ int w_vibrate(lua_State *L) return 0; } +int w_hasBackgroundMusic(lua_State *L) +{ + lua_pushboolean(L, instance()->hasBackgroundMusic()); + return 1; +} + static const luaL_Reg functions[] = { { "getOS", w_getOS }, @@ -104,6 +110,7 @@ static const luaL_Reg functions[] = { "getPowerInfo", w_getPowerInfo }, { "openURL", w_openURL }, { "vibrate", w_vibrate }, + { "hasBackgroundMusic", w_hasBackgroundMusic }, { 0, 0 } }; diff --git a/src/scripts/boot.lua b/src/scripts/boot.lua index c27453f0e..8025cb129 100644 --- a/src/scripts/boot.lua +++ b/src/scripts/boot.lua @@ -373,6 +373,9 @@ function love.init() window = true, video = true, }, + audio = { + mixwithsystem = true, -- Only relevant for Android / iOS. + }, console = false, -- Only relevant for windows. identity = false, appendidentity = false, @@ -492,6 +495,10 @@ function love.init() end end + if love.audio then + love.audio.setMixMode(c.audio.mixwithsystem) + end + -- Our first timestep, because window creation can take some time if love.timer then love.timer.step() diff --git a/src/scripts/boot.lua.h b/src/scripts/boot.lua.h index 21b960d29..b474b2156 100644 --- a/src/scripts/boot.lua.h +++ b/src/scripts/boot.lua.h @@ -684,6 +684,12 @@ const unsigned char boot_lua[] = 0x09, 0x09, 0x09, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a, 0x09, 0x09, 0x09, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a, 0x09, 0x09, 0x7d, 0x2c, 0x0a, + 0x09, 0x09, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x20, 0x3d, 0x20, 0x7b, 0x0a, + 0x09, 0x09, 0x09, 0x6d, 0x69, 0x78, 0x77, 0x69, 0x74, 0x68, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x3d, + 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x20, 0x2d, 0x2d, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x72, 0x65, 0x6c, + 0x65, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, + 0x2f, 0x20, 0x69, 0x4f, 0x53, 0x2e, 0x0a, + 0x09, 0x09, 0x7d, 0x2c, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x20, 0x2d, 0x2d, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x0a, @@ -912,6 +918,12 @@ const unsigned char boot_lua[] = 0x77, 0x2e, 0x69, 0x63, 0x6f, 0x6e, 0x29, 0x29, 0x0a, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0a, + 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x20, 0x74, 0x68, 0x65, + 0x6e, 0x0a, + 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x73, 0x65, 0x74, 0x4d, 0x69, + 0x78, 0x4d, 0x6f, 0x64, 0x65, 0x28, 0x63, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x6d, 0x69, 0x78, 0x77, + 0x69, 0x74, 0x68, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x29, 0x0a, + 0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x2d, 0x2d, 0x20, 0x4f, 0x75, 0x72, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x65, 0x70, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x74, 0x61,