diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 95361da33..3206a1854 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -3203,7 +3203,7 @@ typedef enum : NSUInteger { NSURL *fileURL = [NSURL fileURLWithPath:filepath]; // Setup audio session - BOOL configuredAudio = [OWSAudioSession.shared setRecordCategoryWithAudioActivity:self.voiceNoteAudioActivity]; + BOOL configuredAudio = [OWSAudioSession.shared startRecordingAudioActivity:self.voiceNoteAudioActivity]; if (!configuredAudio) { OWSFail(@"%@ Couldn't configure audio session", self.logTag); [self cancelVoiceMemo]; diff --git a/Signal/src/ViewControllers/ExperienceUpgradesPageViewController.swift b/Signal/src/ViewControllers/ExperienceUpgradesPageViewController.swift index b5dc87592..8d8b2bc63 100644 --- a/Signal/src/ViewControllers/ExperienceUpgradesPageViewController.swift +++ b/Signal/src/ViewControllers/ExperienceUpgradesPageViewController.swift @@ -9,13 +9,6 @@ private class IntroducingCustomNotificationAudioExperienceUpgradeViewController: var buttonAction: ((UIButton) -> Void)? - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - - // Opt users in to the new default sound ("note") after they've seen the splash screen. - OWSSounds.setGlobalNotificationSound(.note) - } - override func loadView() { self.view = UIView.container() diff --git a/Signal/src/environment/NotificationsManager.m b/Signal/src/environment/NotificationsManager.m index 3b65fac5b..7c2503dcf 100644 --- a/Signal/src/environment/NotificationsManager.m +++ b/Signal/src/environment/NotificationsManager.m @@ -25,6 +25,7 @@ @property (nonatomic, readonly) NotificationType notificationPreviewType; @property (nonatomic, readonly) NSMutableArray *notificationHistory; +@property (nonatomic, nullable) OWSAudioPlayer *audioPlayer; @end @@ -238,7 +239,8 @@ } else { if (shouldPlaySound && [Environment.preferences soundInForeground]) { OWSSound sound = [OWSSounds notificationSoundForThread:thread]; - [OWSSounds playSound:sound quiet:YES shouldRespectSilentSwitch:YES]; + self.audioPlayer = [OWSSounds audioPlayerForSound:sound]; + [self.audioPlayer playAsForegroundAlert]; } } }); @@ -343,8 +345,8 @@ } else { if (shouldPlaySound && [Environment.preferences soundInForeground]) { OWSSound sound = [OWSSounds notificationSoundForThread:thread]; - // We play the "quiet" variation of sounds if possible for notifications in the foreground. - [OWSSounds playSound:sound quiet:YES shouldRespectSilentSwitch:YES]; + self.audioPlayer = [OWSSounds audioPlayerForSound:sound]; + [self.audioPlayer playAsForegroundAlert]; } } }); diff --git a/SignalMessaging/attachments/OWSVideoPlayer.swift b/SignalMessaging/attachments/OWSVideoPlayer.swift index f5405e64b..c5b86db31 100644 --- a/SignalMessaging/attachments/OWSVideoPlayer.swift +++ b/SignalMessaging/attachments/OWSVideoPlayer.swift @@ -38,7 +38,7 @@ public class OWSVideoPlayer: NSObject { } public func play() { - OWSAudioSession.shared.setPlaybackCategory(audioActivity: self.audioActivity) + OWSAudioSession.shared.startPlaybackAudioActivity(self.audioActivity) guard let item = avPlayer.currentItem else { owsFail("\(logTag) video player item was unexpectedly nil") diff --git a/SignalMessaging/environment/OWSAudioSession.swift b/SignalMessaging/environment/OWSAudioSession.swift index e892975ff..d6d60d2d6 100644 --- a/SignalMessaging/environment/OWSAudioSession.swift +++ b/SignalMessaging/environment/OWSAudioSession.swift @@ -33,14 +33,30 @@ public class OWSAudioSession: NSObject { private var currentActivities: [Weak] = [] + // Respects hardware mute switch, plays through external speaker, mixes with backround audio + // appropriate for foreground sound effects. + public func startAmbientAudioActivity(_ audioActivity: AudioActivity) { + Logger.debug("\(logTag) in \(#function)") + + startAudioActivity(audioActivity) + + guard currentActivities.count == 0 else { + // We don't want to clobber the audio capabilities configured by (e.g.) media playback or an in-progress call + Logger.info("\(logTag) in \(#function) not touching audio session since another currentActivity exists.") + return + } + + do { + try avAudioSession.setCategory(AVAudioSessionCategoryAmbient) + } catch { + owsFail("\(logTag) in \(#function) failed with error: \(error)") + } + } + // Ignores hardware mute switch, plays through external speaker - public func setPlaybackCategory(audioActivity: AudioActivity) { + public func startPlaybackAudioActivity(_ audioActivity: AudioActivity) { Logger.debug("\(logTag) in \(#function)") - // In general, we should have put the audio session back to it's default - // category when we were done with whatever activity required it to be modified - assert(avAudioSession.category == AVAudioSessionCategorySoloAmbient) - startAudioActivity(audioActivity) do { @@ -50,13 +66,9 @@ public class OWSAudioSession: NSObject { } } - public func setRecordCategory(audioActivity: AudioActivity) -> Bool { + public func startRecordingAudioActivity(_ audioActivity: AudioActivity) -> Bool { Logger.debug("\(logTag) in \(#function)") - // In general, we should have put the audio session back to it's default - // category when we were done with whatever activity required it to be modified - assert(avAudioSession.category == AVAudioSessionCategorySoloAmbient) - assert(avAudioSession.recordPermission() == .granted) startAudioActivity(audioActivity) @@ -104,8 +116,6 @@ public class OWSAudioSession: NSObject { } do { - try avAudioSession.setCategory(AVAudioSessionCategorySoloAmbient) - // When playing audio in Signal, other apps audio (e.g. Music) is paused. // By notifying when we deactivate, the other app can resume playback. try avAudioSession.setActive(false, with: [.notifyOthersOnDeactivation]) diff --git a/SignalMessaging/environment/OWSSounds.h b/SignalMessaging/environment/OWSSounds.h index 223ef11b1..99d40ccfc 100644 --- a/SignalMessaging/environment/OWSSounds.h +++ b/SignalMessaging/environment/OWSSounds.h @@ -48,9 +48,6 @@ typedef NS_ENUM(NSUInteger, OWSSound) { + (nullable NSString *)filenameForSound:(OWSSound)sound; -+ (void)playSound:(OWSSound)sound shouldRespectSilentSwitch:(BOOL)shouldRespectSilentSwitch; -+ (void)playSound:(OWSSound)sound quiet:(BOOL)quiet shouldRespectSilentSwitch:(BOOL)shouldRespectSilentSwitch; - #pragma mark - Notifications + (NSArray *)allNotificationSounds; diff --git a/SignalMessaging/environment/OWSSounds.m b/SignalMessaging/environment/OWSSounds.m index 86f4afa44..60acb3871 100644 --- a/SignalMessaging/environment/OWSSounds.m +++ b/SignalMessaging/environment/OWSSounds.m @@ -17,8 +17,6 @@ NSString *const kOWSSoundsStorageGlobalNotificationKey = @"kOWSSoundsStorageGlob @property (nonatomic, readonly) YapDatabaseConnection *dbConnection; -@property (nonatomic, nullable) OWSAudioPlayer *audioPlayer; - @end #pragma mark - @@ -70,7 +68,6 @@ NSString *const kOWSSoundsStorageGlobalNotificationKey = @"kOWSSoundsStorageGlob @(OWSSound_Bamboo), @(OWSSound_Chord), @(OWSSound_Circles), - @(OWSSound_ClassicNotification), @(OWSSound_Complete), @(OWSSound_Hello), @(OWSSound_Input), @@ -78,6 +75,7 @@ NSString *const kOWSSoundsStorageGlobalNotificationKey = @"kOWSSoundsStorageGlob @(OWSSound_Popcorn), @(OWSSound_Pulse), @(OWSSound_Synth), + @(OWSSound_ClassicNotification), ]; } @@ -115,7 +113,7 @@ NSString *const kOWSSoundsStorageGlobalNotificationKey = @"kOWSSoundsStorageGlob case OWSSound_Synth: return @"Synth"; case OWSSound_ClassicNotification: - return @"Classic"; + return @"Signal Classic"; // Call Audio case OWSSound_Opening: @@ -209,27 +207,6 @@ NSString *const kOWSSoundsStorageGlobalNotificationKey = @"kOWSSoundsStorageGlob return url; } -+ (void)playSound:(OWSSound)sound shouldRespectSilentSwitch:(BOOL)shouldRespectSilentSwitch -{ - [self.sharedManager playSound:sound quiet:NO shouldRespectSilentSwitch:shouldRespectSilentSwitch]; -} - -+ (void)playSound:(OWSSound)sound quiet:(BOOL)quiet shouldRespectSilentSwitch:(BOOL)shouldRespectSilentSwitch -{ - [self.sharedManager playSound:sound quiet:quiet shouldRespectSilentSwitch:shouldRespectSilentSwitch]; -} - -- (void)playSound:(OWSSound)sound quiet:(BOOL)quiet shouldRespectSilentSwitch:(BOOL)shouldRespectSilentSwitch -{ - [self.audioPlayer stop]; - self.audioPlayer = [OWSSounds audioPlayerForSound:sound quiet:quiet]; - if (shouldRespectSilentSwitch) { - [self.audioPlayer playWithCurrentAudioCategory]; - } else { - [self.audioPlayer playWithPlaybackAudioCategory]; - } -} - #pragma mark - Notifications + (OWSSound)defaultNotificationSound @@ -282,11 +259,18 @@ NSString *const kOWSSoundsStorageGlobalNotificationKey = @"kOWSSoundsStorageGlob DDLogDebug(@"%@ writing new default sound to %@", self.logTag, defaultSoundPath); NSURL *_Nullable soundURL = [OWSSounds soundURLForSound:sound quiet:NO]; - OWSAssert(soundURL); + + NSData *soundData = ^{ + if (soundURL) { + return [NSData dataWithContentsOfURL:soundURL]; + } else { + OWSAssert(sound == OWSSound_None); + return [NSData new]; + } + }(); // Quick way to achieve an atomic "copy" operation that allows overwriting if the user has previously specified // a default notification sound. - NSData *soundData = [NSData dataWithContentsOfURL:soundURL]; BOOL success = [soundData writeToFile:defaultSoundPath atomically:YES]; // The globally configured sound the user has configured is unprotected, so that we can still play the sound if the diff --git a/SignalMessaging/utils/OWSAudioPlayer.h b/SignalMessaging/utils/OWSAudioPlayer.h index 98a9a2f13..10a5acfaa 100644 --- a/SignalMessaging/utils/OWSAudioPlayer.h +++ b/SignalMessaging/utils/OWSAudioPlayer.h @@ -38,6 +38,9 @@ typedef NS_ENUM(NSInteger, AudioPlaybackState) { // respects silent switch - (void)playWithCurrentAudioCategory; +// respects silent switch, mixes with others +- (void)playAsForegroundAlert; + // will ensure sound is audible, even if silent switch is enabled - (void)playWithPlaybackAudioCategory; diff --git a/SignalMessaging/utils/OWSAudioPlayer.m b/SignalMessaging/utils/OWSAudioPlayer.m index e01efcaab..4586aea1f 100644 --- a/SignalMessaging/utils/OWSAudioPlayer.m +++ b/SignalMessaging/utils/OWSAudioPlayer.m @@ -99,11 +99,20 @@ NS_ASSUME_NONNULL_BEGIN - (void)playWithPlaybackAudioCategory { OWSAssertIsOnMainThread(); - [OWSAudioSession.shared setPlaybackCategoryWithAudioActivity:self.audioActivity]; + [OWSAudioSession.shared startPlaybackAudioActivity:self.audioActivity]; [self play]; } +- (void)playAsForegroundAlert +{ + OWSAssertIsOnMainThread(); + [OWSAudioSession.shared startAmbientAudioActivity:self.audioActivity]; + + AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); + [self play]; +} + - (void)play { OWSAssertIsOnMainThread();