removed unwanted bar now with waveforms, major updates and enhancements

This commit is contained in:
Mark Gregory
2026-11-07 11:15:40 +00:00
parent ec601f3544
commit 9d0d1cccc8
5 changed files with 145 additions and 34 deletions
+62
View File
@@ -3294,3 +3294,65 @@ extension KJamsCloneTests {
XCTAssertGreaterThan(player.displayTime,position+0.08)
}
}
extension KJamsCloneTests {
func testDJImportContinuesAfterUnreadableFilesAndStalledTags() throws {
let root = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
defer { try? FileManager.default.removeItem(at:root) }
let input = root.appendingPathComponent("Input");try FileManager.default.createDirectory(at:input,withIntermediateDirectories:true)
let format = try XCTUnwrap(AVAudioFormat(standardFormatWithSampleRate:44100,channels:1))
for (index,name) in ["A Slow Tags","B Good","C Good","D Good"].enumerated() {
let samples = try XCTUnwrap(AVAudioPCMBuffer(pcmFormat:format,frameCapacity:1024));samples.frameLength = 1024
for frame in 0..<1024 { samples.floatChannelData![0][frame] = Float(sin(Double(frame)*Double(index+1)*0.1))*0.2 }
let file = try AVAudioFile(forWriting:input.appendingPathComponent(name+".wav"),settings:format.settings);try file.write(from:samples)
}
try Data().write(to:input.appendingPathComponent("AA Empty.wav"))
let library = try Library(url:root.appendingPathComponent("Library.sqlite"))
let importer = Importer(media:root.appendingPathComponent("Media"),audioExtensions:["wav"],includeGraphics:false,continueOnUnreadableAudio:true,metadataTimeout:0.08,metadataLoader:{ url in
if url.lastPathComponent.hasPrefix("A Slow") { try await Task.sleep(nanoseconds:10_000_000_000) }
return [.commonKeyTitle:"Tagged "+url.deletingPathExtension().lastPathComponent]
})
var report = ImportProgress();let began = ProcessInfo.processInfo.systemUptime
let ids = try importer.run([input],library:library,copyMedia:false,progress:{report = $0})
XCTAssertLessThan(ProcessInfo.processInfo.systemUptime-began,3,"A stalled tag read must not hold up later files")
XCTAssertEqual(ids.count,4);XCTAssertEqual(try library.songs().count,4)
XCTAssertEqual(report.total,5);XCTAssertEqual(report.completed,5);XCTAssertEqual(report.skipped,1);XCTAssertTrue(report.finished)
XCTAssertTrue(report.logLines.contains{$0.contains("tag read timed out")})
XCTAssertTrue(report.logLines.contains{$0.contains("AA Empty.wav") && $0.hasPrefix("[SKIPPED]")})
XCTAssertTrue(try library.songs().contains{$0.title == "A Slow Tags"});XCTAssertTrue(try library.songs().contains{$0.title == "Tagged D Good"})
}
func testImportCancellationInterruptsStalledMetadataWait() throws {
let root = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
defer { try? FileManager.default.removeItem(at:root) }
try FileManager.default.createDirectory(at:root,withIntermediateDirectories:true)
let fixture = try XCTUnwrap(Bundle(for:Self.self).resourceURL?.appendingPathComponent("Fixtures/Demo.mp3"))
let library = try Library(url:root.appendingPathComponent("Library.sqlite")),began = ProcessInfo.processInfo.systemUptime
let importer = Importer(media:root.appendingPathComponent("Media"),metadataTimeout:20,metadataLoader:{ _ in try await Task.sleep(nanoseconds:10_000_000_000);return [:] })
XCTAssertThrowsError(try importer.run([fixture],library:library,copyMedia:false,cancelled:{ProcessInfo.processInfo.systemUptime-began > 0.12})) { XCTAssertTrue($0 is CancellationError) }
XCTAssertLessThan(ProcessInfo.processInfo.systemUptime-began,1)
XCTAssertTrue(try library.songs().isEmpty)
}
@MainActor func testLargeDJImportKeepsUIResponsiveAndCompletesEveryInput() async throws {
let root = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
defer { try? FileManager.default.removeItem(at:root) }
let input = root.appendingPathComponent("Input");try FileManager.default.createDirectory(at:input,withIntermediateDirectories:true)
let format = try XCTUnwrap(AVAudioFormat(standardFormatWithSampleRate:44100,channels:1))
for index in 0..<128 {
let buffer = try XCTUnwrap(AVAudioPCMBuffer(pcmFormat:format,frameCapacity:1024));buffer.frameLength = 1024
for frame in 0..<1024 { buffer.floatChannelData![0][frame] = Float(sin(Double(frame)*0.1+Double(index)))*0.2 }
let file = try AVAudioFile(forWriting:input.appendingPathComponent(String(format:"Unique %04d.wav",index)),settings:format.settings);try file.write(from:buffer)
}
for index in 0..<512 { try FileManager.default.copyItem(at:input.appendingPathComponent("Unique 0000.wav"),to:input.appendingPathComponent(String(format:"Duplicate %04d.wav",index))) }
let system = DJSystem(storageURL:root.appendingPathComponent("DJ"))
system.importFiles([input]);XCTAssertTrue(system.importing);XCTAssertTrue(system.importLogVisible)
var heartbeat = false;Task { @MainActor in heartbeat = true }
system.crossfader = 0.75
for _ in 0..<1000 where system.importing { try await Task.sleep(nanoseconds:10_000_000) }
XCTAssertTrue(heartbeat);XCTAssertFalse(system.importing);XCTAssertEqual(system.crossfader,0.75)
let report = try XCTUnwrap(system.lastImportReport)
XCTAssertEqual(report.completed,640);XCTAssertEqual(report.total,640);XCTAssertEqual(report.skipped,512)
XCTAssertNil(report.failure);XCTAssertEqual(system.songs.count,128,"Every distinct track is saved, while repeated audio remains deduplicated")
system.automaticWaveforms.cancel()
for _ in 0..<200 where system.automaticWaveforms.isRunning { try await Task.sleep(nanoseconds:5_000_000) }
}
}