Skip to content

Commit 64f46ad

Browse files
authored
LOOP-1099: Promote AlertSoundPlayer to LoopKit (#74)
* LOOP-1179: Implement Alert Sounds Introduces a new "AlertSoundVendor" abstraction, which DeviceManagers now can implement in order to vend sounds to play with alerts. The sounds are simply named as part of the DeviceAlert to play. Sound configuration is still up to the device's settings UI. This adds the ability to: 1. Copy Alert Sounds to /Library/Sounds from each device manager (they need to be there for UserNotifications to find them, and for convenience we play them from that same location in-app) 2. Play those sounds either in the in-app modal or the UserNotification * Promote AlertSoundPlayer to LoopKit ...that way, it can be used elsewhere for playing alert sounds. * PR Feedback: Make DeviceAlert.SoundName a struct * More PR feedback * Build fix * More PR feedback: Make SoundName a first-class enum (and name it just "Sound") * PR Feedback * Remove unused import
1 parent 4ebbfd7 commit 64f46ad

File tree

3 files changed

+5
-38
lines changed

3 files changed

+5
-38
lines changed

Loop.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@
332332
892D7C5123B54A15008A9656 /* CarbEntryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892D7C5023B54A14008A9656 /* CarbEntryViewController.swift */; };
333333
892FB4CD22040104005293EC /* OverridePresetRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892FB4CC22040104005293EC /* OverridePresetRow.swift */; };
334334
892FB4CF220402C0005293EC /* OverrideSelectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892FB4CE220402C0005293EC /* OverrideSelectionController.swift */; };
335+
893C9F852446F54E00CD4185 /* Environment+Dismiss.swift in Sources */ = {isa = PBXBuildFile; fileRef = 893C9F842446F54E00CD4185 /* Environment+Dismiss.swift */; };
335336
894F6DD3243BCBDB00CCE676 /* Environment+SizeClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 894F6DD2243BCBDB00CCE676 /* Environment+SizeClass.swift */; };
336337
894F6DD7243C047300CCE676 /* View+Position.swift in Sources */ = {isa = PBXBuildFile; fileRef = 894F6DD6243C047300CCE676 /* View+Position.swift */; };
337338
894F6DD9243C060600CCE676 /* ScalablePositionedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 894F6DD8243C060600CCE676 /* ScalablePositionedText.swift */; };
@@ -343,7 +344,6 @@
343344
895788B1242E69A2002CB114 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 895788A9242E69A1002CB114 /* Color.swift */; };
344345
895788B2242E69A2002CB114 /* CircularAccessoryButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 895788AA242E69A1002CB114 /* CircularAccessoryButtonStyle.swift */; };
345346
895788B3242E69A2002CB114 /* ActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 895788AB242E69A2002CB114 /* ActionButton.swift */; };
346-
893C9F852446F54E00CD4185 /* Environment+Dismiss.swift in Sources */ = {isa = PBXBuildFile; fileRef = 893C9F842446F54E00CD4185 /* Environment+Dismiss.swift */; };
347347
895FE0952201234000FCF18A /* OverrideSelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 895FE0942201234000FCF18A /* OverrideSelectionViewController.swift */; };
348348
8968B1122408B3520074BB48 /* UIFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8968B1112408B3520074BB48 /* UIFont.swift */; };
349349
8968B114240C55F10074BB48 /* LoopSettingsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8968B113240C55F10074BB48 /* LoopSettingsTests.swift */; };
@@ -1019,6 +1019,7 @@
10191019
892D7C5023B54A14008A9656 /* CarbEntryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarbEntryViewController.swift; sourceTree = "<group>"; };
10201020
892FB4CC22040104005293EC /* OverridePresetRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverridePresetRow.swift; sourceTree = "<group>"; };
10211021
892FB4CE220402C0005293EC /* OverrideSelectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverrideSelectionController.swift; sourceTree = "<group>"; };
1022+
893C9F842446F54E00CD4185 /* Environment+Dismiss.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Environment+Dismiss.swift"; sourceTree = "<group>"; };
10221023
894F6DD2243BCBDB00CCE676 /* Environment+SizeClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Environment+SizeClass.swift"; sourceTree = "<group>"; };
10231024
894F6DD6243C047300CCE676 /* View+Position.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "View+Position.swift"; path = "WatchApp Extension/Views/View+Position.swift"; sourceTree = SOURCE_ROOT; };
10241025
894F6DD8243C060600CCE676 /* ScalablePositionedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScalablePositionedText.swift; sourceTree = "<group>"; };
@@ -1030,7 +1031,6 @@
10301031
895788A9242E69A1002CB114 /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = "<group>"; };
10311032
895788AA242E69A1002CB114 /* CircularAccessoryButtonStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CircularAccessoryButtonStyle.swift; sourceTree = "<group>"; };
10321033
895788AB242E69A2002CB114 /* ActionButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionButton.swift; sourceTree = "<group>"; };
1033-
893C9F842446F54E00CD4185 /* Environment+Dismiss.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Environment+Dismiss.swift"; sourceTree = "<group>"; };
10341034
895FE0942201234000FCF18A /* OverrideSelectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OverrideSelectionViewController.swift; sourceTree = "<group>"; };
10351035
8968B1112408B3520074BB48 /* UIFont.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIFont.swift; sourceTree = "<group>"; };
10361036
8968B113240C55F10074BB48 /* LoopSettingsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopSettingsTests.swift; sourceTree = "<group>"; };

Loop/Managers/DeviceAlert/InAppModalDeviceAlertPresenter.swift

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,6 @@
88

99
import Foundation
1010
import LoopKit
11-
import AudioToolbox
12-
import AVFoundation
13-
14-
15-
public protocol AlertSoundPlayer {
16-
func vibrate()
17-
func play(url: URL)
18-
}
1911

2012
public class InAppModalDeviceAlertPresenter: DeviceAlertPresenter {
2113

@@ -31,11 +23,11 @@ public class InAppModalDeviceAlertPresenter: DeviceAlertPresenter {
3123
typealias TimerFactoryFunction = (TimeInterval, Bool, (() -> Void)?) -> Timer
3224
private let newTimerFunc: TimerFactoryFunction
3325

34-
private let soundPlayer: AlertSoundPlayer
26+
private let soundPlayer: DeviceAlertSoundPlayer
3527

3628
init(rootViewController: UIViewController,
3729
deviceAlertManagerResponder: DeviceAlertManagerResponder,
38-
soundPlayer: AlertSoundPlayer = AVSoundPlayer(),
30+
soundPlayer: DeviceAlertSoundPlayer = DeviceAVSoundPlayer(),
3931
newActionFunc: @escaping ActionFactoryFunction = UIAlertAction.init,
4032
newTimerFunc: TimerFactoryFunction? = nil) {
4133
self.rootViewController = rootViewController
@@ -185,28 +177,3 @@ extension InAppModalDeviceAlertPresenter {
185177
}
186178
}
187179
}
188-
189-
private class AVSoundPlayer: AlertSoundPlayer {
190-
private var soundEffect: AVAudioPlayer?
191-
private let log = DiagnosticLog(category: "AVSoundPlayer")
192-
193-
func vibrate() {
194-
AudioServicesPlayAlertSound(SystemSoundID(kSystemSoundID_Vibrate))
195-
}
196-
197-
func play(url: URL) {
198-
DispatchQueue.main.async {
199-
do {
200-
// The AVAudioPlayer has to remain around until the sound completes playing. A cleaner way might be
201-
// to wait until that completes, then delete it, but seems overkill.
202-
let soundEffect = try AVAudioPlayer(contentsOf: url)
203-
self.soundEffect = soundEffect
204-
if !soundEffect.play() {
205-
self.log.default("couldn't play sound (app may be in the background): %@", url.absoluteString)
206-
}
207-
} catch {
208-
self.log.error("couldn't play sound %@: %@", url.absoluteString, String(describing: error))
209-
}
210-
}
211-
}
212-
}

LoopTests/Managers/DeviceAlert/InAppModalDeviceAlertPresenterTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class InAppModalDeviceAlertPresenterTests: XCTestCase {
5757
}
5858
}
5959

60-
class MockSoundPlayer: AlertSoundPlayer {
60+
class MockSoundPlayer: DeviceAlertSoundPlayer {
6161
var vibrateCalled = false
6262
func vibrate() {
6363
vibrateCalled = true

0 commit comments

Comments
 (0)