Merge pull request #1978 from euharrison/master
Audio mix with other apps for iOS
This commit is contained in:
commit
c4385090ab
@ -4,6 +4,7 @@
|
||||
|
||||
- Fix iOS bug which would break size of views when video is displayed with controls on a non full-screen React view. [#1931](https://github.com/react-native-community/react-native-video/pull/1931)
|
||||
- Fix video dimensions being undefined when playing HLS in ios. [#1992](https://github.com/react-native-community/react-native-video/pull/1992)
|
||||
- Add support for audio mix with other apps for iOS. [#1978](https://github.com/react-native-community/react-native-video/pull/1978)
|
||||
|
||||
### Version 5.1.0-alpha5
|
||||
|
||||
|
@ -289,6 +289,7 @@ var styles = StyleSheet.create({
|
||||
* [ignoreSilentSwitch](#ignoresilentswitch)
|
||||
* [maxBitRate](#maxbitrate)
|
||||
* [minLoadRetryCount](#minLoadRetryCount)
|
||||
* [mixWithOthers](#mixWithOthers)
|
||||
* [muted](#muted)
|
||||
* [paused](#paused)
|
||||
* [pictureInPicture](#pictureinpicture)
|
||||
@ -531,6 +532,14 @@ minLoadRetryCount={5} // retry 5 times
|
||||
|
||||
Platforms: Android ExoPlayer
|
||||
|
||||
#### mixWithOthers
|
||||
Controls how Audio mix with other apps.
|
||||
* **"inherit" (default)** - Use the default AVPlayer behavior
|
||||
* **"mix"** - Audio from this video mixes with audio from other apps.
|
||||
* **"duck"** - Reduces the volume of other apps while audio from this video plays.
|
||||
|
||||
Platforms: iOS
|
||||
|
||||
#### muted
|
||||
Controls whether the audio is muted
|
||||
* **false (default)** - Don't mute audio
|
||||
|
@ -52,6 +52,7 @@ class VideoPlayer extends Component {
|
||||
paused: true,
|
||||
skin: 'custom',
|
||||
ignoreSilentSwitch: null,
|
||||
mixWithOthers: null,
|
||||
isBuffering: false,
|
||||
filter: FilterType.NONE,
|
||||
filterEnabled: true
|
||||
@ -155,6 +156,18 @@ class VideoPlayer extends Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderMixWithOthersControl(mixWithOthers) {
|
||||
const isSelected = (this.state.mixWithOthers == mixWithOthers);
|
||||
|
||||
return (
|
||||
<TouchableOpacity onPress={() => { this.setState({mixWithOthers: mixWithOthers}) }}>
|
||||
<Text style={[styles.controlOption, {fontWeight: isSelected ? "bold" : "normal"}]}>
|
||||
{mixWithOthers}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
|
||||
renderCustomSkin() {
|
||||
const flexCompleted = this.getCurrentTimePercentage() * 100;
|
||||
const flexRemaining = (1 - this.getCurrentTimePercentage()) * 100;
|
||||
@ -170,6 +183,7 @@ class VideoPlayer extends Component {
|
||||
volume={this.state.volume}
|
||||
muted={this.state.muted}
|
||||
ignoreSilentSwitch={this.state.ignoreSilentSwitch}
|
||||
mixWithOthers={this.state.mixWithOthers}
|
||||
resizeMode={this.state.resizeMode}
|
||||
onLoad={this.onLoad}
|
||||
onBuffer={this.onBuffer}
|
||||
@ -226,10 +240,16 @@ class VideoPlayer extends Component {
|
||||
<View style={styles.generalControls}>
|
||||
{
|
||||
(Platform.OS === 'ios') ?
|
||||
<View style={styles.ignoreSilentSwitchControl}>
|
||||
{this.renderIgnoreSilentSwitchControl('ignore')}
|
||||
{this.renderIgnoreSilentSwitchControl('obey')}
|
||||
</View> : null
|
||||
<>
|
||||
<View style={styles.ignoreSilentSwitchControl}>
|
||||
{this.renderIgnoreSilentSwitchControl('ignore')}
|
||||
{this.renderIgnoreSilentSwitchControl('obey')}
|
||||
</View>
|
||||
<View style={styles.mixWithOthersControl}>
|
||||
{this.renderMixWithOthersControl('mix')}
|
||||
{this.renderMixWithOthersControl('duck')}
|
||||
</View>
|
||||
</> : null
|
||||
}
|
||||
</View>
|
||||
|
||||
@ -257,6 +277,7 @@ class VideoPlayer extends Component {
|
||||
volume={this.state.volume}
|
||||
muted={this.state.muted}
|
||||
ignoreSilentSwitch={this.state.ignoreSilentSwitch}
|
||||
mixWithOthers={this.state.mixWithOthers}
|
||||
resizeMode={this.state.resizeMode}
|
||||
onLoad={this.onLoad}
|
||||
onBuffer={this.onBuffer}
|
||||
@ -313,10 +334,16 @@ class VideoPlayer extends Component {
|
||||
<View style={styles.generalControls}>
|
||||
{
|
||||
(Platform.OS === 'ios') ?
|
||||
<View style={styles.ignoreSilentSwitchControl}>
|
||||
{this.renderIgnoreSilentSwitchControl('ignore')}
|
||||
{this.renderIgnoreSilentSwitchControl('obey')}
|
||||
</View> : null
|
||||
<>
|
||||
<View style={styles.ignoreSilentSwitchControl}>
|
||||
{this.renderIgnoreSilentSwitchControl('ignore')}
|
||||
{this.renderIgnoreSilentSwitchControl('obey')}
|
||||
</View>
|
||||
<View style={styles.mixWithOthersControl}>
|
||||
{this.renderMixWithOthersControl('mix')}
|
||||
{this.renderMixWithOthersControl('duck')}
|
||||
</View>
|
||||
</> : null
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
@ -399,6 +426,12 @@ const styles = StyleSheet.create({
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
mixWithOthersControl: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
controlOption: {
|
||||
alignSelf: 'center',
|
||||
fontSize: 11,
|
||||
|
@ -67,6 +67,7 @@ static int const RCTVideoUnset = -1;
|
||||
BOOL _playWhenInactive;
|
||||
BOOL _pictureInPicture;
|
||||
NSString * _ignoreSilentSwitch;
|
||||
NSString * _mixWithOthers;
|
||||
NSString * _resizeMode;
|
||||
BOOL _fullscreen;
|
||||
BOOL _fullscreenAutorotate;
|
||||
@ -108,6 +109,7 @@ static int const RCTVideoUnset = -1;
|
||||
_playWhenInactive = false;
|
||||
_pictureInPicture = false;
|
||||
_ignoreSilentSwitch = @"inherit"; // inherit, ignore, obey
|
||||
_mixWithOthers = @"inherit"; // inherit, mix, duck
|
||||
#if TARGET_OS_IOS
|
||||
_restoreUserInterfaceForPIPStopCompletionHandler = NULL;
|
||||
#endif
|
||||
@ -861,18 +863,42 @@ static int const RCTVideoUnset = -1;
|
||||
[self applyModifiers];
|
||||
}
|
||||
|
||||
- (void)setMixWithOthers:(NSString *)mixWithOthers
|
||||
{
|
||||
_mixWithOthers = mixWithOthers;
|
||||
[self applyModifiers];
|
||||
}
|
||||
|
||||
- (void)setPaused:(BOOL)paused
|
||||
{
|
||||
if (paused) {
|
||||
[_player pause];
|
||||
[_player setRate:0.0];
|
||||
} else {
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
AVAudioSessionCategory category = nil;
|
||||
AVAudioSessionCategoryOptions options = nil;
|
||||
|
||||
if([_ignoreSilentSwitch isEqualToString:@"ignore"]) {
|
||||
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
|
||||
category = AVAudioSessionCategoryPlayback;
|
||||
} else if([_ignoreSilentSwitch isEqualToString:@"obey"]) {
|
||||
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
|
||||
category = AVAudioSessionCategoryAmbient;
|
||||
}
|
||||
|
||||
|
||||
if([_mixWithOthers isEqualToString:@"mix"]) {
|
||||
options = AVAudioSessionCategoryOptionMixWithOthers;
|
||||
} else if([_mixWithOthers isEqualToString:@"duck"]) {
|
||||
options = AVAudioSessionCategoryOptionDuckOthers;
|
||||
}
|
||||
|
||||
if (category != nil && options != nil) {
|
||||
[session setCategory:category withOptions:options error:nil];
|
||||
} else if (category != nil && options == nil) {
|
||||
[session setCategory:category error:nil];
|
||||
} else if (category == nil && options != nil) {
|
||||
[session setCategory:session.category withOptions:options error:nil];
|
||||
}
|
||||
|
||||
if (@available(iOS 10.0, *) && !_automaticallyWaitsToMinimizeStalling) {
|
||||
[_player playImmediatelyAtRate:_rate];
|
||||
} else {
|
||||
|
@ -35,6 +35,7 @@ RCT_EXPORT_VIEW_PROPERTY(playInBackground, BOOL);
|
||||
RCT_EXPORT_VIEW_PROPERTY(playWhenInactive, BOOL);
|
||||
RCT_EXPORT_VIEW_PROPERTY(pictureInPicture, BOOL);
|
||||
RCT_EXPORT_VIEW_PROPERTY(ignoreSilentSwitch, NSString);
|
||||
RCT_EXPORT_VIEW_PROPERTY(mixWithOthers, NSString);
|
||||
RCT_EXPORT_VIEW_PROPERTY(rate, float);
|
||||
RCT_EXPORT_VIEW_PROPERTY(seek, NSDictionary);
|
||||
RCT_EXPORT_VIEW_PROPERTY(currentTime, float);
|
||||
|
Loading…
Reference in New Issue
Block a user