Skip to content

Commit

Permalink
Sniff audio clips (readium#403)
Browse files Browse the repository at this point in the history
  • Loading branch information
mickael-menu authored Mar 23, 2024
1 parent 8607390 commit 6365bb9
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ All notable changes to this project will be documented in this file. Take a look
* Fixed starting the TTS from the current EPUB position.
* [#396](https://github.com/readium/swift-toolkit/issues/396) Ensure we stop the activity indicator when an EPUB resource fails to load correctly (contributed by [@ettore](https://github.com/readium/swift-toolkit/pull/397)).

#### Streamer

* [#399](https://github.com/readium/swift-toolkit/discussions/399) Zipped Audio Books and standalone audio files are now recognized.


## [2.6.1]

Expand Down
5 changes: 4 additions & 1 deletion Sources/Shared/Toolkit/Media Type/MediaType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ public struct MediaType: Hashable, Loggable {
public static let divina = MediaType("application/divina+zip", name: "Digital Visual Narratives", fileExtension: "divina")!
public static let divinaManifest = MediaType("application/divina+json", name: "Digital Visual Narratives", fileExtension: "json")!
public static let epub = MediaType("application/epub+zip", name: "EPUB", fileExtension: "epub")!
public static let flac = MediaType("audio/flac", fileExtension: "flac")!
public static let gif = MediaType("image/gif", fileExtension: "gif")!
public static let gz = MediaType("application/gzip", fileExtension: "gz")!
public static let html = MediaType("text/html", fileExtension: "html")!
Expand All @@ -266,7 +267,9 @@ public struct MediaType: Hashable, Loggable {
public static let lcpStatusDocument = MediaType("application/vnd.readium.license.status.v1.0+json")!
public static let lpf = MediaType("application/lpf+zip", fileExtension: "lpf")!
public static let mp3 = MediaType("audio/mpeg", fileExtension: "mp3")!
public static let mpeg = MediaType("video/mpeg", fileExtension: "mpeg")!
public static let mp4 = MediaType("audio/mp4", fileExtension: "mp4")!
public static let mpegAudio = MediaType("audio/mpeg", fileExtension: "mpeg")!
public static let mpegVideo = MediaType("video/mpeg", fileExtension: "mpeg")!
public static let ncx = MediaType("application/x-dtbncx+xml", fileExtension: "ncx")!
public static let ogg = MediaType("audio/ogg", fileExtension: "oga")!
public static let ogv = MediaType("video/ogg", fileExtension: "ogv")!
Expand Down
37 changes: 36 additions & 1 deletion Sources/Shared/Toolkit/Media Type/MediaTypeSniffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public extension MediaType {
/// You can register additional sniffers globally by modifying this list.
/// The sniffers order is important, because some media types are subsets of other media types.
static var sniffers: [Sniffer] = [
sniffHTML, sniffOPDS, sniffLCPLicense, sniffBitmap,
sniffHTML, sniffOPDS, sniffLCPLicense, sniffBitmap, sniffAudio,
sniffWebPub, sniffW3CWPUB, sniffEPUB, sniffLPF, sniffArchive, sniffPDF,
]

Expand Down Expand Up @@ -392,6 +392,41 @@ public extension MediaType {
return nil
}

/// Sniffs an audio clip.
private static func sniffAudio(context: MediaTypeSnifferContext) -> MediaType? {
if context.hasFileExtension("aac") || context.hasMediaType("audio/aac") {
return .aac
}
if context.hasFileExtension("aiff", "aif", "aifc") || context.hasMediaType("audio/aiff", "audio/x-aiff") {
return .aiff
}
if context.hasFileExtension("flac") || context.hasMediaType("audio/flac") {
return .flac
}
if context.hasFileExtension("mp3") {
return .mp3
}
if context.hasFileExtension("mp4", "m4a", "m4b", "m4p", "m4r", "alac") || context.hasMediaType("audio/mp4") {
return .mp4
}
if context.hasMediaType("audio/mpeg") {
return .mpegAudio
}
if context.hasFileExtension("ogg", "oga", "mogg") || context.hasMediaType("audio/ogg") {
return .ogg
}
if context.hasFileExtension("opus") || context.hasMediaType("audio/opus") {
return .opus
}
if context.hasFileExtension("wav", "wave") || context.hasMediaType("audio/wav", "audio/x-wav", "audio/wave") {
return .wav
}
if context.hasFileExtension("webm") || context.hasMediaType("audio/webm") {
return .webmAudio
}
return nil
}

/// Sniffs the media types declared in the Document Types section of the app's `Info.plist`.
private static func sniffDocumentTypes(_ context: MediaTypeSnifferContext) -> MediaType? {
func sniff(_ documentType: DocumentType) -> MediaType? {
Expand Down
61 changes: 61 additions & 0 deletions Tests/SharedTests/Toolkit/Media Type/MediaTypeSnifferTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,19 @@ class MediaTypeSnifferTests: XCTestCase {
XCTAssertEqual(MediaType.of(fixtures.url(for: "audiobook-wrongtype.json")), .readiumAudiobookManifest)
}

func testSniffAAC() {
XCTAssertEqual(MediaType.of(fileExtension: "aac"), .aac)
XCTAssertEqual(MediaType.of(mediaType: "audio/aac"), .aac)
}

func testSniffAIFF() {
XCTAssertEqual(MediaType.of(fileExtension: "aiff"), .aiff)
XCTAssertEqual(MediaType.of(fileExtension: "aif"), .aiff)
XCTAssertEqual(MediaType.of(fileExtension: "aifc"), .aiff)
XCTAssertEqual(MediaType.of(mediaType: "audio/aiff"), .aiff)
XCTAssertEqual(MediaType.of(mediaType: "audio/x-aiff"), .aiff)
}

func testSniffBMP() {
XCTAssertEqual(MediaType.of(fileExtension: "bmp"), .bmp)
XCTAssertEqual(MediaType.of(fileExtension: "dib"), .bmp)
Expand Down Expand Up @@ -98,6 +111,11 @@ class MediaTypeSnifferTests: XCTestCase {
XCTAssertEqual(MediaType.of(fixtures.url(for: "epub.unknown")), .epub)
}

func testSniffFLAC() {
XCTAssertEqual(MediaType.of(fileExtension: "flac"), .flac)
XCTAssertEqual(MediaType.of(mediaType: "audio/flac"), .flac)
}

func testSniffGIF() {
XCTAssertEqual(MediaType.of(fileExtension: "gif"), .gif)
XCTAssertEqual(MediaType.of(mediaType: "image/gif"), .gif)
Expand Down Expand Up @@ -176,6 +194,36 @@ class MediaTypeSnifferTests: XCTestCase {
XCTAssertEqual(MediaType.of(fixtures.url(for: "lpf-index-html.unknown")), .lpf)
}

func testSniffMP3() {
XCTAssertEqual(MediaType.of(fileExtension: "mp3"), .mp3)
}

func testSniffMP4() {
XCTAssertEqual(MediaType.of(fileExtension: "mp4"), .mp4)
XCTAssertEqual(MediaType.of(fileExtension: "m4a"), .mp4)
XCTAssertEqual(MediaType.of(fileExtension: "m4b"), .mp4)
XCTAssertEqual(MediaType.of(fileExtension: "m4p"), .mp4)
XCTAssertEqual(MediaType.of(fileExtension: "m4r"), .mp4)
XCTAssertEqual(MediaType.of(fileExtension: "alac"), .mp4)
XCTAssertEqual(MediaType.of(mediaType: "audio/mp4"), .mp4)
}

func testSniffMPEG() {
XCTAssertEqual(MediaType.of(mediaType: "audio/mpeg"), .mpegAudio)
}

func testSniffOGG() {
XCTAssertEqual(MediaType.of(fileExtension: "ogg"), .ogg)
XCTAssertEqual(MediaType.of(fileExtension: "oga"), .ogg)
XCTAssertEqual(MediaType.of(fileExtension: "mogg"), .ogg)
XCTAssertEqual(MediaType.of(mediaType: "audio/ogg"), .ogg)
}

func testSniffOPUS() {
XCTAssertEqual(MediaType.of(fileExtension: "opus"), .opus)
XCTAssertEqual(MediaType.of(mediaType: "audio/opus"), .opus)
}

func testSniffPDF() {
XCTAssertEqual(MediaType.of(fileExtension: "pdf"), .pdf)
XCTAssertEqual(MediaType.of(mediaType: "application/pdf"), .pdf)
Expand All @@ -194,11 +242,24 @@ class MediaTypeSnifferTests: XCTestCase {
XCTAssertEqual(MediaType.of(mediaType: "image/tiff-fx"), .tiff)
}

func testSniffWAV() {
XCTAssertEqual(MediaType.of(fileExtension: "wav"), .wav)
XCTAssertEqual(MediaType.of(fileExtension: "wave"), .wav)
XCTAssertEqual(MediaType.of(mediaType: "audio/wav"), .wav)
XCTAssertEqual(MediaType.of(mediaType: "audio/x-wav"), .wav)
XCTAssertEqual(MediaType.of(mediaType: "audio/wave"), .wav)
}

func testSniffWebP() {
XCTAssertEqual(MediaType.of(fileExtension: "webp"), .webp)
XCTAssertEqual(MediaType.of(mediaType: "image/webp"), .webp)
}

func testSniffWebM() {
XCTAssertEqual(MediaType.of(fileExtension: "webm"), .webmAudio)
XCTAssertEqual(MediaType.of(mediaType: "audio/webm"), .webmAudio)
}

func testSniffWebPub() {
XCTAssertEqual(MediaType.of(fileExtension: "webpub"), .readiumWebPub)
XCTAssertEqual(MediaType.of(mediaType: "application/webpub+zip"), .readiumWebPub)
Expand Down

0 comments on commit 6365bb9

Please sign in to comment.