Skip to content

Commit

Permalink
AudioPlayer features #58: Store all audio as AudioPlayer instances to…
Browse files Browse the repository at this point in the history
… support playing the next audio when the device screen off.
  • Loading branch information
filimo committed Jan 12, 2020
1 parent 0845b49 commit 55ed488
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 151 deletions.
29 changes: 22 additions & 7 deletions ReaderTranslator.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,6 @@
F0D31C5123491C23003CF86B /* GTranslatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0D31C5023491C23003CF86B /* GTranslatorView.swift */; };
F0D31C5223491C23003CF86B /* GTranslatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0D31C5023491C23003CF86B /* GTranslatorView.swift */; };
F0D3551C23A6BE3C009FBA74 /* GTranslatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0D3551B23A6BE3C009FBA74 /* GTranslatorView.swift */; };
F0DAB5E323B66DE400C1A4D3 /* TestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0DAB5E223B66DE400C1A4D3 /* TestView.swift */; };
F0DADAE5239BE8C200CFE2B1 /* SwiftSoup in Frameworks */ = {isa = PBXBuildFile; productRef = F0DADAE4239BE8C200CFE2B1 /* SwiftSoup */; };
F0EDE34B236418E000E0B81C /* DOMEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0EE0A0F23478C86004A5EAD /* DOMEvent.swift */; };
F0EDE34D23641B1300E0B81C /* Stack.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0EDE34C23641B1300E0B81C /* Stack.swift */; };
Expand Down Expand Up @@ -532,7 +531,6 @@
F0D2E333234BA49000D95994 /* Safari.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Safari.swift; sourceTree = "<group>"; };
F0D31C5023491C23003CF86B /* GTranslatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GTranslatorView.swift; sourceTree = "<group>"; };
F0D3551B23A6BE3C009FBA74 /* GTranslatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GTranslatorView.swift; sourceTree = "<group>"; };
F0DAB5E223B66DE400C1A4D3 /* TestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestView.swift; sourceTree = "<group>"; };
F0EDE34C23641B1300E0B81C /* Stack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stack.swift; sourceTree = "<group>"; };
F0EDFB1E239E2F210048CFD1 /* BookmarksView_Controls_ActionMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksView_Controls_ActionMenu.swift; sourceTree = "<group>"; };
F0EDFB21239E467B0048CFD1 /* ReaderView_Pdf_Toolbar_PlayButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderView_Pdf_Toolbar_PlayButtons.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -816,7 +814,6 @@
F00AD753239627EB005FAFE1 /* PlayerContols */,
F0AB182323A5501C00A71CA6 /* ViewModes */,
F0120379239182DA008D0B47 /* PlayerContentView.swift */,
F0DAB5E223B66DE400C1A4D3 /* TestView.swift */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -1098,6 +1095,7 @@
F0120370239182DA008D0B47 /* Frameworks */,
F0120371239182DA008D0B47 /* Resources */,
F01F89DB23A5F7800082153E /* SwiftLint */,
F00A084E23CB550E00027C9F /* Incremental Build */,
);
buildRules = (
);
Expand Down Expand Up @@ -1309,6 +1307,24 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
F00A084E23CB550E00027C9F /* Incremental Build */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "Incremental Build";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nbuildNumber=$(/usr/libexec/PlistBuddy -c \"Print CFBundleVersion\" \"${PROJECT_DIR}/${INFOPLIST_FILE}\")\nbuildNumber=$(($buildNumber + 1))\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $buildNumber\" \"${PROJECT_DIR}/${INFOPLIST_FILE}\"\n";
};
F01F89DB23A5F7800082153E /* SwiftLint */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
Expand Down Expand Up @@ -1379,7 +1395,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n# buildNumber=$(/usr/libexec/PlistBuddy -c \"Print CFBundleVersion\" \"${PROJECT_DIR}/${INFOPLIST_FILE}\")\n# buildNumber=$(($buildNumber + 1))\n# /usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $buildNumber\" \"${PROJECT_DIR}/${INFOPLIST_FILE}\"\n";
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nbuildNumber=$(/usr/libexec/PlistBuddy -c \"Print CFBundleVersion\" \"${PROJECT_DIR}/${INFOPLIST_FILE}\")\nbuildNumber=$(($buildNumber + 1))\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $buildNumber\" \"${PROJECT_DIR}/${INFOPLIST_FILE}\"\n";
};
/* End PBXShellScriptBuildPhase section */

Expand Down Expand Up @@ -1428,7 +1444,6 @@
F02B04C523A2930D00F93B84 /* ConnectionView.swift in Sources */,
F0D3551C23A6BE3C009FBA74 /* GTranslatorView.swift in Sources */,
F0120378239182DA008D0B47 /* SceneDelegate.swift in Sources */,
F0DAB5E323B66DE400C1A4D3 /* TestView.swift in Sources */,
F033F41223A6D3A800605325 /* DirectoryObserver.swift in Sources */,
F08EBB0523956202009025D3 /* FileListView.swift in Sources */,
F046182E23A3A4AF0041E726 /* ConnectionClientStatus.swift in Sources */,
Expand Down Expand Up @@ -1845,7 +1860,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.4.2;
MARKETING_VERSION = 1.8.9;
PRODUCT_BUNDLE_IDENTIFIER = by.filimo.ReaderTranslatorMac;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
Expand All @@ -1872,7 +1887,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.4.2;
MARKETING_VERSION = 1.8.9;
PRODUCT_BUNDLE_IDENTIFIER = by.filimo.ReaderTranslatorMac;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
Expand Down
2 changes: 1 addition & 1 deletion ReaderTranslatorMac/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>1733</string>
<string>1762</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.education</string>
<key>LSMinimumSystemVersion</key>
Expand Down
42 changes: 21 additions & 21 deletions ReaderTranslatorPlayer/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>LSSupportsOpeningDocumentsInPlace</key>
<false/>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
Expand All @@ -22,24 +20,24 @@
<key>NSDocumentClass</key>
<string></string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>m4a</string>
</array>
<key>CFBundleTypeName</key>
<string>MPEG-4 Audio</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>public.mpeg-4-audio</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>m4a</string>
</array>
<key>CFBundleTypeName</key>
<string>MPEG-4 Audio</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>public.mpeg-4-audio</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
Expand All @@ -54,9 +52,11 @@
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<string>29</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<false/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
Expand Down
120 changes: 69 additions & 51 deletions ReaderTranslatorPlayer/Store/AudioStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ final class AudioStore: NSObject, ObservableObject {
private(set) var player: AVAudioPlayer?
private var someObservationContext = ""

@Published private(set) var allAudioPlayers = [AVAudioPlayer]()

@Published var currentStatus = "0.0/0.0"
@Published var isPlaying = false {
willSet {
Expand All @@ -44,6 +46,7 @@ final class AudioStore: NSObject, ObservableObject {
setupNowPlaying()
}
}

@Published var sleepAfter = 0

private override init() {
Expand All @@ -57,31 +60,87 @@ final class AudioStore: NSObject, ObservableObject {
} catch {
Logger.log(type: .error, value: error)
}
if player == nil {

saveAllAudioPlayer()
if let lastAudio = lastAudio { openAudio(url: lastAudio) }
}


initMPRemoteCommandCenter()
}
}

extension AudioStore {
func openAudio(url: URL?) {
guard let url = url else { return }

if player != nil { player?.pause() }
player = allAudioPlayers.first { $0.url == url }
guard let player = player else { return }
player.rate = rate
player.delegate = self
player.enableRate = true
lastAudio = url
}

func play(_ url: URL? = nil) {
guard let url = url ?? lastAudio else {
isPlaying = false
return
}
openAudio(url: url)
isPlaying = true
setupNowPlaying()
}

func prevPlay() {
guard let index = (allAudioPlayers.firstIndex { $0.url == player?.url }) else { return }
if index == 0 { return }
play(allAudioPlayers[index - 1].url)
}

func nextPlay() {
guard let index = (allAudioPlayers.firstIndex { $0.url == player?.url }) else { return }
if allAudioPlayers.indices.contains(index + 1) == false { return }
play(allAudioPlayers[index + 1].url)
}

func saveAllAudioPlayer() {
allAudioPlayers = FileStore.shared.files
.compactMap { url in
do {
return try AVAudioPlayer(contentsOf: url)
} catch {
Logger.log(type: .error, value: (error, url))
}
return nil
}
}
}


extension AudioStore: AVAudioPlayerDelegate {
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
if flag {
nextPlay()
}
}
}

extension AudioStore {
private func initMPRemoteCommandCenter() {
let commandCenter = MPRemoteCommandCenter.shared()

commandCenter.previousTrackCommand.isEnabled = true
commandCenter.previousTrackCommand.addTarget { _ in
self.prevPlay()
return .success
}

commandCenter.playCommand.isEnabled = true
commandCenter.playCommand.addTarget { _ in
self.isPlaying = true
return .success
}

commandCenter.pauseCommand.isEnabled = true
commandCenter.pauseCommand.addTarget { _ in
self.isPlaying = false
Expand All @@ -94,15 +153,15 @@ extension AudioStore {
return .success
}
}

private func setupNowPlaying() {
var nowPlayingInfo = [String: Any]()

nowPlayingInfo[MPMediaItemPropertyTitle] = player?.url?.lastPathComponent
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = player?.currentTime
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = player?.duration
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player?.rate

MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}
}
Expand Down Expand Up @@ -137,44 +196,3 @@ extension AudioStore {
return "The timer will turn off \(time)"
}
}

extension AudioStore {
func openAudio(url: URL) {
do {
player = try AVAudioPlayer(contentsOf: url)
guard let player = player else { return }
player.delegate = self
player.enableRate = true
player.rate = rate
lastAudio = url
} catch {
Logger.log(type: .error, value: error)
}
}

func play(_ url: URL? = nil) {
guard let url = url ?? lastAudio else {
isPlaying = false
return
}
openAudio(url: url)
isPlaying = true
setupNowPlaying()
}

func prevPlay() {
play(FileStore.shared.prevFile(file: lastAudio))
}

func nextPlay() {
play(FileStore.shared.nextFile(file: lastAudio))
}
}

extension AudioStore: AVAudioPlayerDelegate {
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
if flag {
nextPlay()
}
}
}
11 changes: 3 additions & 8 deletions ReaderTranslatorPlayer/Store/FileStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import Foundation

final class FileStore: ObservableObject {
private init() {}
static let shared = FileStore()

static private var directoryObserver: DirectoryObserver?
Expand All @@ -30,25 +31,19 @@ final class FileStore: ObservableObject {
}
return documentsUrl.appendingPathComponent("/Inbox")
}()

private init() {

}

func prevFile(file: URL?) -> URL? {
guard let file = file else { return nil }
guard let current = files.firstIndex(of: file) else { return nil }
let index = files.index(before: current)

return files.indices.contains(index) ? files[index] : nil
return files.indices.contains(current - 1) ? files[current - 1] : nil
}

func nextFile(file: URL?) -> URL? {
guard let file = file else { return nil }
guard let current = files.firstIndex(of: file) else { return nil }
let index = files.index(after: current)

return files.indices.contains(index) ? files[index] : nil
return files.indices.contains(current + 1) ? files[current + 1] : nil
}
}

Loading

0 comments on commit 55ed488

Please sign in to comment.