Merge pull request #1978 from euharrison/master
Audio mix with other apps for iOS
This commit is contained in:
		| @@ -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> | ||||
|                   <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> | ||||
|                   <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,16 +863,40 @@ 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) { | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user