Skip to content
Snippets Groups Projects
Commit 7915a325 authored by Consonne's avatar Consonne
Browse files

Initial commit

parents
No related branches found
No related tags found
No related merge requests found
Showing
with 463 additions and 0 deletions
project/obj
License
=======
The MIT License (MIT)
Copyright (c) 2016 Jonatan van Hove
Copyright (c) 2016 Martin Jonasson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
OpenFL iOS Audio Extension
==========
Enables setting the iOS audio session as "ambient" to allow playback of external audio while playing a game. It also exposes a way to know if external music is playing or not.
Installation
============
You can easily install this extension using haxelib:
haxelib git extension-ios-audio https://github.com/grapefrukt/extension-ios-audio
To add it to a Lime or OpenFL project, add this to your project file:
<haxelib name="extension-ios-audio" if="ios" />
Installation
============
This extension was originally built by [Joon for Glitchnap](http://www.glitchnap.com/) and has had further work on it by [grapefrukt](http://grapefrukt.com)
Usage
=====
This extension provides four functions, use them as follows:
```haxe
#if ios
// to fix the audio going silent on interruptions, call this function _once_
// as your game starts
extension.iosaudio.IOSAudio.fixInterrupt();
// to enable audio ducking (ie. allowing other things to play audio
// over your game) call this immediately on startup
extension.iosaudio.IOSAudio.enableAmbient();
// you can use the hasExternalMusicPlaying property to decide whether
// to play your own music or not
if (extension.iosaudio.IOSAudio.hasExternalMusicPlaying) {
// don't play
} else {
// do play
}
// should you ever want to put things back the way they were you can
// disable ducking again
extension.iosaudio.IOSAudio.disableAmbient();
#end
```
block-icons/ios_audio.png

589 B

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<palette>
<block tag="iosaudio_has_external_music_playing" spec="Is external music playing ? [i:mobile] (ios)" code="#if ios extension.iosaudio.IOSAudio.hasExternalMusicPlaying() #end " type="normal" color="charcoal" returns="boolean">
<fields>
</fields>
</block>
<block tag="iosaudio_enable_disable_ambient" spec="%0 ambient [i:mobile] (ios)" code="#if ios extension.iosaudio.IOSAudio.~Ambient(); #end" type="action" color="charcoal" help="enables setting the iOS audio session as 'ambient' to allow playback of external audio while playing a game" returns="void">
<fields>
<dropdown order="0">
<choices>
<c text="enable" code="enable"></c>
<c text="disable" code="disable"></c>
</choices>
</dropdown>
</fields>
</block>
</palette>
package extension.iosaudio;
#if cpp
import cpp.Lib;
#elseif neko
import neko.Lib;
#end
class IOSAudio {
/**
* Allows you to check if external music (or any audio) is playing
*/
public static var hasExternalMusicPlaying(get, never):Bool;
/**
* Call once at startup to add the fix for interrupted sound. Can be used independent of ambient settings.
* Do _not_ call multiple times.
*/
public static function fixInterrupt():Void {
#if ios
iosaudio_fixinterrupt();
#end
}
/**
* Sets your audio session as ambient which allows mixing with other audio sources
*/
public static function enableAmbient():Void {
#if ios
iosaudio_enableambient();
#end
}
/**
* Returns your audio session to the default state, not allowing any other audio to be played
*/
public static function disableAmbient():Void {
#if ios
iosaudio_disableambient ();
#end
}
static function get_hasExternalMusicPlaying():Bool {
#if ios
return iosaudio_hasexternalmusicplaying();
#else
return false;
#end
}
#if ios
private static var iosaudio_fixinterrupt = Lib.load("iosaudio", "iosaudio_fixinterrupt", 0);
private static var iosaudio_enableambient = Lib.load("iosaudio", "iosaudio_enableambient", 0);
private static var iosaudio_disableambient = Lib.load("iosaudio", "iosaudio_disableambient", 0);
private static var iosaudio_hasexternalmusicplaying = Lib.load("iosaudio", "iosaudio_hasexternalmusicplaying", 0);
#end
}
\ No newline at end of file
package extension.iosaudio;
import haxe.macro.Expr;
import haxe.macro.Context;
class StencylEngineModifier
{
#if macro
public static function build()
{
haxe.macro.Compiler.addMetadata("@:build(extension.iosaudio.StencylEngineModifier.changeMain())", "com.stencyl.Config");//
}
#end
public static function changeMain():Array<Field>
{
var fields:Array<Field> = Context.getBuildFields();
#if ios
for(field in fields){
if (field.name == "load")
{
switch (field.kind){
case FieldType.FFun(func):
switch (func.expr.expr)
{
case EBlock(a) :
trace("IOSAudioExtension : Modifying load in Config to include 'enableAmbient' ...");
var newC = "#if ios
extension.iosaudio.IOSAudio.enableAmbient();
#end";
var oldC = haxe.macro.ExprTools.toString(func.expr);
var tc = "{" + newC +oldC.substr(1);
var c = Context.parse(tc, func.expr.pos );
func.expr = c;
default:
}
default:
}
}
}
#end
return fields;
}
}
\ No newline at end of file
{
"name": "extension-ios-audio",
"url": "http://www.grapefrukt.com",
"license": "MIT",
"tags": [],
"description": "Makes legacy OpenFL projects respect other audio sources on iOS",
"version": "1.0.0",
"releasenote": "",
"contributors": [ "grapefrukt", "joonturbo" ],
"dependencies": {}
}
icon.png 0 → 100644
icon.png

1.46 KiB

<?xml version="1.0" encoding="utf-8"?>
<project>
<haxeflag name="--macro" value="extension.iosaudio.StencylEngineModifier.build()" if="ios" />
<ndll name="extension_ios_audio" if="ios" />
</project>
\ No newline at end of file
name=IOS Audio
description=enables setting the iOS audio session as "ambient" to allow playback of external audio while playing a game
author=grapefrukt ( openfl extension) && yoplalala (stencyl adapter)
website=https://github.com/grapefrukt/extension-ios-audio
version=0.2
compatibility=ios
\ No newline at end of file
File added
File added
File added
File added
<xml>
<include name="${HXCPP}/build-tool/BuildCommon.xml"/>
<files id="common">
<compilerflag value="-Iinclude"/>
<file name="common/ExternalInterface.cpp"/>
</files>
<files id="iphone">
<compilerflag value="-IiPhone/include"/>
<compilerflag value="-Iinclude"/>
<file name="iphone/OpenFLIOSAudio.mm"/>
</files>
<target id="NDLL" output="${LIBPREFIX}extension_ios_audio${debug_extra}${LIBEXTRA}" tool="linker" toolid="${STD_MODULE_LINK}">
<outdir name="../ndll/${BINDIR}"/>
<ext value=".ndll" if="windows || mac || linux" />
<files id="common"/>
<files id="iphone" if="iphone"/>
</target>
<target id="default">
<target id="NDLL"/>
</target>
</xml>
\ No newline at end of file
#ifndef STATIC_LINK
#define IMPLEMENT_API
#endif
#if defined(HX_WINDOWS) || defined(HX_MACOS) || defined(HX_LINUX)
#define NEKO_COMPATIBLE
#endif
#include <hx/CFFI.h>
#include <stdio.h>
#include <hxcpp.h>
#include "OpenFLIOSAudio.h"
using namespace openfliosaudio;
static value iosaudio_fixinterrupt() {
fixinterrupt();
return alloc_null();
}
DEFINE_PRIM (iosaudio_fixinterrupt, 0);;
static value iosaudio_enableambient() {
enableambient();
return alloc_null();
}
DEFINE_PRIM (iosaudio_enableambient, 0);;
static value iosaudio_disableambient() {
disableambient();
return alloc_null();
}
DEFINE_PRIM (iosaudio_disableambient, 0);;
static value iosaudio_hasexternalmusicplaying() {
return alloc_bool(hasexternalmusicplaying());
}
DEFINE_PRIM(iosaudio_hasexternalmusicplaying, 0);
extern "C" int extension_ios_audio_register_prims() { return 0; }
\ No newline at end of file
#ifndef OPENFLIOSAUDIO_H
#define OPENFLIOSAUDIO_H
namespace openfliosaudio {
void fixinterrupt();
void enableambient();
void disableambient();
bool hasexternalmusicplaying();
}
#endif
#include <OpenFLIOSAudio.h>
#define __STDC_FORMAT_MACROS // non needed in C, only in C++
#import <Foundation/Foundation.h>
#include <inttypes.h>
#import <AVFoundation/AVFoundation.h>
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
typedef void (*FunctionType)();
static ALCcontext *alcContext = nil;
static BOOL isAmbient = false;
@interface InterruptObserver : NSObject {
}
- (void) onAudioSessionEvent: (NSNotification *) notification;
@end
@implementation InterruptObserver
- (void) onAudioSessionEvent: (NSNotification *) notification
{
//Check the type of notification, especially if you are sending multiple AVAudioSession events here
if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) {
NSLog(@"Interruption notification received!");
//Check to see if it was a Begin interruption
if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeBegan]]) {
NSLog(@"Interruption began!");
alcContext = alcGetCurrentContext();
// Deactivate the current audio session
AudioSessionSetActive(NO);
// set the current context to NULL will 'shutdown' openAL
alcMakeContextCurrent(NULL);
// now suspend your context to 'pause' your sound world
alcSuspendContext(alcContext);
} else {
NSLog(@"Interruption ended!");
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setActive: YES error: nil];
// The ambient property gets lots when the session is deactivated, so that needs to be set again
if (isAmbient) {
UInt32 category = kAudioSessionCategory_AmbientSound;
AudioSessionSetProperty ( kAudioSessionProperty_AudioCategory, sizeof (category), &category );
}
// Reactivate the current audio session
AudioSessionSetActive(YES);
// Restore OpenAL context
alcMakeContextCurrent(alcContext);
// finally, 'unpause' the context
alcProcessContext(alcContext);
}
}
}
@end
namespace openfliosaudio {
void fixinterrupt() {
// get the shared audio session
AVAudioSession *session = [AVAudioSession sharedInstance];
[[NSNotificationCenter defaultCenter] addObserver: [[InterruptObserver alloc] init]
selector: @selector(onAudioSessionEvent:)
name: AVAudioSessionInterruptionNotification
object: session];
}
void enableambient() {
isAmbient = true;
// get the shared audio session
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *setCategoryError = nil;
// set it as ambient
if (![session setCategory:AVAudioSessionCategoryAmbient
withOptions:AVAudioSessionCategoryOptionMixWithOthers
error:&setCategoryError]) {
// it'd be nice to handle the error here, but i don't know what to do with it
//NSLog(@"ERROR SETTING AVAUDIOSESSION");
}
//NSLog(@"SETTING AVAUDIOSESSION TO DUCK (play others)");
}
void disableambient() {
// same thing as enable, but different category
isAmbient = false;
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *setCategoryError = nil;
if (![session setCategory:AVAudioSessionCategorySoloAmbient
withOptions:AVAudioSessionCategoryOptionDuckOthers
error:&setCategoryError]) {
// handle error
//NSLog(@"ERROR SETTING AVAUDIOSESSION");
}
//NSLog(@"SETTING AVAUDIOSESSION TO NOT DUCK (duck others)");
}
bool hasexternalmusicplaying() {
BOOL isOtherAudioPlaying = [[AVAudioSession sharedInstance] isOtherAudioPlaying];
return isOtherAudioPlaying;
}
}
\ No newline at end of file
rebuild 0 → 100755
#!/bin/sh
# exit script on error
set -e
echo "Removing old build products"
# remove old stuff
rm -rf ndll
rm -rf project/obj
echo "Building native libraries for OpenFL"
# generate native libraries
lime rebuild ./project ios -clean
echo "Complete!"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment