Skip to content

Commit

Permalink
Add a basic audio reader
Browse files Browse the repository at this point in the history
  • Loading branch information
mickael-menu committed Apr 21, 2023
1 parent 31882f9 commit 9562e1b
Show file tree
Hide file tree
Showing 5 changed files with 267 additions and 1 deletion.
90 changes: 90 additions & 0 deletions TestApp/Sources/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,42 @@
<string>org.readium.lcpl</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Readium Audiobook</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>org.readium.audiobook</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Readium Audiobook Manifest</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>org.readium.audiobook.manifest</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>LCP Protected Audiobook</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>org.readium.lcpa</string>
</array>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
Expand Down Expand Up @@ -332,6 +368,60 @@
<string>application/webpub+zip</string>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
<string>public.archive</string>
<string>public.zip-archive</string>
</array>
<key>UTTypeIdentifier</key>
<string>org.readium.audiobook</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>audiobook</string>
<string>AUDIOBOOK</string>
</array>
<key>public.mime-type</key>
<string>application/audiobook+zip</string>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
<string>public.content</string>
</array>
<key>UTTypeIdentifier</key>
<string>org.readium.audiobook.manifest</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.mime-type</key>
<string>application/audiobook+json</string>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
<string>public.archive</string>
<string>public.zip-archive</string>
</array>
<key>UTTypeIdentifier</key>
<string>org.readium.lcpa</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>lcpa</string>
<string>LCPA</string>
</array>
<key>public.mime-type</key>
<string>application/audiobook+lcp</string>
</dict>
</dict>
</array>
</dict>
</plist>
46 changes: 46 additions & 0 deletions TestApp/Sources/Reader/Audiobook/AudiobookModule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// Copyright 2023 Readium Foundation. All rights reserved.
// Use of this source code is governed by the BSD-style license
// available in the top-level LICENSE file of the project.
//

import Foundation
import R2Navigator
import R2Shared
import UIKit

final class AudiobookModule: ReaderFormatModule {
weak var delegate: ReaderFormatModuleDelegate?

init(delegate: ReaderFormatModuleDelegate?) {
self.delegate = delegate
}

func supports(_ publication: Publication) -> Bool {
publication.conforms(to: .audiobook)
}

@MainActor
func makeReaderViewController(
for publication: Publication,
locator: Locator?,
bookId: Book.Id,
books: BookRepository,
bookmarks: BookmarkRepository,
highlights: HighlightRepository
) async throws -> UIViewController {
guard publication.metadata.identifier != nil else {
throw ReaderError.epubNotValid
}

let viewController = try await AudiobookViewController(
publication: publication,
locator: locator,
bookId: bookId,
books: books,
bookmarks: bookmarks
)
viewController.moduleDelegate = delegate
return viewController
}
}
130 changes: 130 additions & 0 deletions TestApp/Sources/Reader/Audiobook/AudiobookViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
//
// Copyright 2023 Readium Foundation. All rights reserved.
// Use of this source code is governed by the BSD-style license
// available in the top-level LICENSE file of the project.
//

import Combine
import Foundation
import R2Navigator
import R2Shared
import SwiftUI
import UIKit

class AudiobookViewController: ReaderViewController<AudioNavigator>, AudioNavigatorDelegate {
private let model: AudiobookViewModel

init(
publication: Publication,
locator: Locator?,
bookId: Book.Id,
books: BookRepository,
bookmarks: BookmarkRepository
) {
let navigator = AudioNavigator(
publication: publication,
initialLocation: locator
)

model = AudiobookViewModel(
publication: publication,
navigator: navigator
)

super.init(
navigator: navigator,
publication: publication,
bookId: bookId,
books: books,
bookmarks: bookmarks
)

navigator.delegate = self
}

private lazy var readerController =
UIHostingController(rootView: AudiobookReader(model: model))

override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = .white

addChild(readerController)
view.addSubview(readerController.view)
readerController.view.frame = view.bounds
readerController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
readerController.didMove(toParent: self)

navigator.play()
}

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigator.pause()
}

// MARK: - AudioNavigatorDelegate

func navigator(_ navigator: MediaNavigator, playbackDidChange info: MediaPlaybackInfo) {
model.playbackDidChange(info: info)
}
}

class AudiobookViewModel: ObservableObject {
private let publication: Publication
private let navigator: AudioNavigator

@Published var cover: UIImage?
@Published var playback: MediaPlaybackInfo = .init()

init(publication: Publication, navigator: AudioNavigator) {
self.publication = publication
self.navigator = navigator

Task {
cover = publication.cover
}
}

func playbackDidChange(info: MediaPlaybackInfo) {
playback = info
}

func playPause() {
navigator.playPause()
}
}

struct AudiobookReader: View {
@ObservedObject var model: AudiobookViewModel

var body: some View {
VStack {
Spacer()

if let cover = model.cover {
Image(uiImage: cover)
.resizable()
.aspectRatio(contentMode: .fit)
.padding()
}

HStack {
Spacer()

IconButton(
systemName: model.playback.state != .paused
? "pause.fill"
: "play.fill"
) {
model.playPause()
}

Spacer()
}

Spacer(minLength: 40)
}
}
}
1 change: 0 additions & 1 deletion TestApp/Sources/Reader/EPUB/EPUBModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ final class EPUBModule: ReaderFormatModule {

func supports(_ publication: Publication) -> Bool {
publication.conforms(to: .epub)
|| publication.readingOrder.allAreHTML
}

@MainActor
Expand Down
1 change: 1 addition & 0 deletions TestApp/Sources/Reader/ReaderModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ final class ReaderModule: ReaderModuleAPI {
self.highlights = highlights

formatModules = [
AudiobookModule(delegate: self),
CBZModule(delegate: self),
EPUBModule(delegate: self),
PDFModule(delegate: self),
Expand Down

0 comments on commit 9562e1b

Please sign in to comment.