Skip to content

Commit

Permalink
Fix build on tvOS and Linux.
Browse files Browse the repository at this point in the history
  • Loading branch information
Fabian Zwick committed Oct 23, 2024
1 parent cda6b2e commit c3b2f0e
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 15 deletions.
4 changes: 2 additions & 2 deletions Source/Mp3/Mp3FileReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class Mp3FileReader {

let readHandle = try FileHandle(forReadingFrom: URL(fileURLWithPath: path))
defer {
if #available(iOS 13.0, *) {
if #available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) {
try? readHandle.close()
} else {
readHandle.closeFile()
Expand All @@ -84,7 +84,7 @@ class Mp3FileReader {

private func read(bytesCount: Int, from fileHandle: FileHandle) throws -> Data {
let result = try {
if #available(iOS 13.4, *) {
if #available(macOS 10.15.4, iOS 13.4, watchOS 6.2, tvOS 13.4, *) {
return try fileHandle.read(upToCount: bytesCount)
} else {
return fileHandle.readData(ofLength: bytesCount)
Expand Down
50 changes: 37 additions & 13 deletions Source/Mp3/Mp3FileWriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,23 @@ class Mp3FileWriter {
if toPath != fromPath {
return toPath
}

return FileManager.default.temporaryDirectory.appendingPathComponent("\(UUID().uuidString).mp3").path
}()

defer {
if temporaryPath != toPath {
try? FileManager.default.removeItem(atPath: temporaryPath)
}
}

try eventuallyCreateIntermediatesDirectoriesFor(path: temporaryPath)
try newId3TagData.write(to: URL(fileURLWithPath: temporaryPath))

// Create file handles
let readHandle = try FileHandle(forReadingFrom: URL(fileURLWithPath: fromPath))
defer {
if #available(iOS 13.0, *) {
if #available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) {
try? readHandle.close()
} else {
readHandle.closeFile()
Expand All @@ -44,41 +44,41 @@ class Mp3FileWriter {

let writeHandle = try FileHandle(forWritingTo: URL(fileURLWithPath: temporaryPath))
defer {
if #available(iOS 13.0, *) {
if #available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) {
try? writeHandle.close()
} else {
writeHandle.closeFile()
}
}

// Seek over the tag of the existing file, then copy the rest in chunks
if #available(iOS 13.4, *) {
if #available(macOS 10.15.4, iOS 13.4, watchOS 6.2, tvOS 13.4, *) {
try writeHandle.seekToEnd()
} else {
writeHandle.seekToEndOfFile()
}

if let currentId3TagData = currentId3TagData {
if #available(iOS 13.0, *) {
if #available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) {
try readHandle.seek(toOffset: UInt64(currentId3TagData.count))
} else {
readHandle.seek(toFileOffset: UInt64(currentId3TagData.count))
}
}

var isFinished = false
while !isFinished {
try autoreleasepool {
let work = {
let chunk = try {
if #available(iOS 13.4, *) {
if #available(macOS 10.15.4, iOS 13.4, watchOS 6.2, tvOS 13.4, *) {
return try readHandle.read(upToCount: 131072) // 128 KB
} else {
return readHandle.readData(ofLength: 131072) // 128 KB
}
}()

if let chunk, !chunk.isEmpty {
if #available(iOS 13.4, *) {
if #available(macOS 10.15.4, iOS 13.4, watchOS 6.2, tvOS 13.4, *) {
try writeHandle.write(contentsOf: chunk)
} else {
writeHandle.write(chunk)
Expand All @@ -87,11 +87,35 @@ class Mp3FileWriter {
isFinished = true
}
}

#if canImport(ObjectiveC)
// autoreleasepool is only needed in Objective-C environment (not on Linux)
try autoreleasepool(invoking: work)
#else
try work()
#endif
}

// Replace the file
if temporaryPath != toPath {
#if os(Linux)
// For some reason the FileManager.replaceItemAt(_:withItemAt:) doesn't work on Linux and fails with `NSFileWriteUnknownError`
let backupPath = URL(fileURLWithPath: toPath).appendingPathExtension("tmp").path
try FileManager.default.copyItem(atPath: toPath, toPath: backupPath)
defer {
try? FileManager.default.removeItem(atPath: backupPath)
}

do {
try FileManager.default.removeItem(atPath: toPath)
try FileManager.default.copyItem(atPath: temporaryPath, toPath: toPath)
} catch {
try? FileManager.default.copyItem(atPath: backupPath, toPath: toPath)
throw error
}
#else
_ = try FileManager.default.replaceItemAt(validPath, withItemAt: URL(fileURLWithPath: temporaryPath))
#endif
}
}

Expand Down

0 comments on commit c3b2f0e

Please sign in to comment.