Skip to content

Commit

Permalink
Refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
Fabian Zwick committed Oct 10, 2024
1 parent 9639e17 commit 4b87c84
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 44 deletions.
43 changes: 3 additions & 40 deletions Source/ID3TagEditor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,46 +68,9 @@ public class ID3TagEditor {
ID3 tag).
*/
public func write(tag: ID3Tag, to path: String, andSaveTo newPath: String? = nil) throws {
guard let newPath else {
let mp3 = try mp3FileReader.readFileFrom(path: path)
let currentTag = try self.id3TagParser.parse(mp3: mp3)
let mp3WithId3Tag = try mp3WithID3TagBuilder.build(mp3: mp3, newId3Tag: tag, currentId3Tag: currentTag)
try mp3FileWriter.write(mp3: mp3WithId3Tag, path: path)
return
}

let currentTag = try read(from: path)
let newTag = try ID3TagCreatorFactory.make().create(id3Tag: tag)
try mp3FileWriter.write(mp3: newTag, path: newPath)

// Create file handles
let readHandle = try FileHandle(forReadingFrom: URL(fileURLWithPath: path))
defer {
readHandle.closeFile()
}

let writeHandle = try FileHandle(forWritingTo: URL(fileURLWithPath: newPath))
defer {
writeHandle.closeFile()
}

// Seek over the tag of the existing file, then copy the rest in chunks
readHandle.seek(toFileOffset: 0)
writeHandle.seekToEndOfFile()

if let currentTag {
let tagSizeWithHeader = UInt64(currentTag.properties.size) + UInt64(ID3TagConfiguration().headerSize())
readHandle.seek(toFileOffset: tagSizeWithHeader)
}

var isFinished = false
while !isFinished {
autoreleasepool {
let chunk = readHandle.readData(ofLength: 65536) // 64 KB
writeHandle.write(chunk)
isFinished = chunk.isEmpty
}
}
let newId3TagData = try mp3WithID3TagBuilder.build(mp3: Data(), newId3Tag: tag, currentId3Tag: nil)
let currentId3Tag = try read(from: path)
try mp3FileWriter.write(newId3TagData: newId3TagData, currentId3Tag: currentId3Tag, fromPath: path, toPath: newPath ?? path)
}

/**
Expand Down
56 changes: 53 additions & 3 deletions Source/Mp3/Mp3FileWriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,59 @@
import Foundation

class Mp3FileWriter {
func write(mp3: Data, path: String) throws {
try eventuallyCreateIntermediatesDirectoriesFor(path: path)
try mp3.write(to: URL(fileURLWithPath: path))
func write(newId3TagData: Data, currentId3Tag: ID3Tag?, fromPath: String, toPath: String) throws {
// Create a temporary file for the new mp3
let temporaryPath = {
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 {
readHandle.closeFile()
}

let writeHandle = try FileHandle(forWritingTo: URL(fileURLWithPath: temporaryPath))
defer {
writeHandle.closeFile()
}

// Seek over the tag of the existing file, then copy the rest in chunks
writeHandle.seekToEndOfFile()

if let validCurrentId3Tag = currentId3Tag {
let tagSizeWithHeader = UInt64(validCurrentId3Tag.properties.size) + UInt64(ID3TagConfiguration().headerSize())
readHandle.seek(toFileOffset: tagSizeWithHeader)
} else {
readHandle.seek(toFileOffset: 0)
}

var isFinished = false
while !isFinished {
autoreleasepool {
let chunk = readHandle.readData(ofLength: 65536) // 64 KB
writeHandle.write(chunk)
isFinished = chunk.isEmpty
}
}

// Replace the file
if temporaryPath != toPath {
_ = try FileManager.default.replaceItemAt(URL(fileURLWithPath: toPath), withItemAt: URL(fileURLWithPath: temporaryPath))
}
}

private func eventuallyCreateIntermediatesDirectoriesFor(path: String) throws {
Expand Down
4 changes: 3 additions & 1 deletion Source/Mp3/Mp3WithID3TagBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ class Mp3WithID3TagBuilder {
tagSizeWithHeader = Int(validCurrentId3Tag.properties.size) + ID3TagConfiguration().headerSize()
}
var mp3WithTag = try id3TagCreator.create(id3Tag: newId3Tag)
mp3WithTag.append(mp3.subdata(in: tagSizeWithHeader..<mp3.count))
if !mp3.isEmpty {
mp3WithTag.append(mp3.subdata(in: tagSizeWithHeader..<mp3.count))
}
return mp3WithTag
}
}

0 comments on commit 4b87c84

Please sign in to comment.