broken changes
This commit is contained in:
@@ -20,6 +20,27 @@ struct DJXMLBinding: Codable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
struct DJXMLOutput: Codable {
|
||||
var key: String
|
||||
var action: String
|
||||
var status: UInt8
|
||||
var number: UInt8
|
||||
var on: UInt8
|
||||
var off: UInt8
|
||||
var flipped: Bool
|
||||
func packet(active: Bool) -> [UInt8] { [status,number,(active != flipped) ? on : off] }
|
||||
static func parse(_ output: [String:Any],binding: DJXMLBinding) -> Self? {
|
||||
let supported = ["A Play","B Play","A Cue button","B Cue button","A Sync","B Sync","A Headphones","B Headphones","A Loop","B Loop"] + ["A","B"].flatMap { d in (1...4).map{d+" Hot cue \($0)"} }
|
||||
guard supported.contains(binding.action),binding.status & 0xF0 == 0x90 else { return nil }
|
||||
let channel = output["midiChannel"] as? Int ?? Int(binding.status & 15)
|
||||
let number = output["midiData"] as? Int ?? Int(binding.number)
|
||||
let type = output["midiMessageType"] as? Int ?? 1
|
||||
guard (0...15).contains(channel),(0...127).contains(number),[0,1,3].contains(type) else { return nil }
|
||||
func byte(_ key: String,_ fallback: Int) -> UInt8 { UInt8(min(127,max(0,(output[key] as? NSNumber)?.intValue ?? fallback))) }
|
||||
return .init(key:binding.key,action:binding.action,status:UInt8((type == 0 ? 0x80 : type == 1 ? 0x90 : 0xB0)+channel),number:UInt8(number),on:byte("midiMaxValue",127),off:byte("midiDisabledValue",Int(byte("midiMinValue",0))),flipped:output["flipped"] as? Bool ?? false)
|
||||
}
|
||||
}
|
||||
|
||||
struct DJXMLProfile: Codable, Identifiable {
|
||||
var id: String
|
||||
var name: String
|
||||
@@ -29,6 +50,7 @@ struct DJXMLProfile: Codable, Identifiable {
|
||||
var total: Int
|
||||
var aliases: [String]?
|
||||
var adapter: String?
|
||||
var outputs: [DJXMLOutput]?
|
||||
var report: String {
|
||||
"\(name)\n\(bindings.count) supported bindings of \(total) control entries.\n\n" +
|
||||
(adapter == "Mixtrack Go" ? "Uses the dedicated Mixtrack Go adapter for 14-bit tempo, relative jog, pad modes and transport/mode feedback.\n\n" : "") +
|
||||
@@ -40,7 +62,7 @@ struct DJXMLProfile: Codable, Identifiable {
|
||||
(root["schemeVersion"] as? Int == 1 || root["schemeVersion"] as? String == "1") else { throw failure("Expected a djay mapping XML property list with schemeVersion 1.") }
|
||||
let controls = root["controls"] as? [[String:Any]] ?? []
|
||||
guard controls.count <= 20000 else { throw failure("Mapping contains too many controls.") }
|
||||
var bindings = [DJXMLBinding](),issues = Set<String>(),blocked = Set<String>()
|
||||
var bindings = [DJXMLBinding](),outputs = [DJXMLOutput](),issues = Set<String>(),blocked = Set<String>()
|
||||
func address(_ c: [String:Any]) -> (UInt8,UInt8)? {
|
||||
guard let channel = c["midiChannel"] as? Int,(0...15).contains(channel),let number = c["midiData"] as? Int,(0...127).contains(number),let type = c["midiMessageType"] as? Int,[1,3,6].contains(type) else { return nil }
|
||||
return (UInt8((type == 1 ? 0x90 : type == 3 ? 0xB0 : 0xE0)+channel),UInt8(number))
|
||||
@@ -63,13 +85,17 @@ struct DJXMLProfile: Codable, Identifiable {
|
||||
blocked.insert(key);issues.insert("\(path): relative control is unsupported for this action.");continue
|
||||
}
|
||||
bindings.append(.init(status:status,number:number,action:action,mode:mode,flipped:c["flipped"] as? Bool ?? false,pickup:c["pickupMode"] as? Bool ?? false))
|
||||
if c["output"] != nil { issues.insert("\(path): XML LED/display output is not implemented; input is supported where listed.") }
|
||||
if let output = c["output"] as? [String:Any] {
|
||||
if let feedback = DJXMLOutput.parse(output,binding:bindings.last!) { outputs.append(feedback) }
|
||||
else { issues.insert("\(path): this XML output definition is not supported.") }
|
||||
}
|
||||
}
|
||||
let grouped = Dictionary(grouping:bindings,by:{$0.key})
|
||||
for (key,group) in grouped where Set(group.map(\.action)).count > 1 || Set(group.map(\.mode)).count > 1 || Set(group.map(\.flipped)).count > 1 {
|
||||
blocked.insert(key);issues.insert("MIDI \(key): conflicting assignments disabled.")
|
||||
}
|
||||
bindings = grouped.keys.sorted().compactMap { blocked.contains($0) ? nil : grouped[$0]?.first }
|
||||
outputs.removeAll { blocked.contains($0.key) }
|
||||
if !blocked.isEmpty { issues.insert("All bindings sharing an unsupported/conditional address are disabled to prevent accidental actions.") }
|
||||
if root["customClassName"] != nil { issues.insert("Device-specific djay custom processor is unavailable; only independent standard MIDI bindings are enabled.") }
|
||||
if root["outputs"] != nil { issues.insert("Device output/display definitions are not executed.") }
|
||||
@@ -79,7 +105,7 @@ struct DJXMLProfile: Codable, Identifiable {
|
||||
bindings = MixtrackGoProtocol.mappings(source:0).map { .init(status:$0.status,number:$0.number,action:$0.action,mode:$0.mode,flipped:false,pickup:false) }
|
||||
issues.insert("Mixtrack Go uses KJMix Pro’s dedicated protocol adapter, including its pad-mode state. Stems, sampler and FX modes remain unavailable.")
|
||||
}
|
||||
return .init(id:root["uuid"] as? String ?? filename,name:filename,endpoint:aliases.first ?? filename,bindings:bindings,issues:issues.sorted(),total:controls.filter{$0["headingTitle"] == nil}.count,aliases:aliases,adapter:adapter)
|
||||
return .init(id:root["uuid"] as? String ?? filename,name:filename,endpoint:aliases.first ?? filename,bindings:bindings,issues:issues.sorted(),total:controls.filter{$0["headingTitle"] == nil}.count,aliases:aliases,adapter:adapter,outputs:outputs)
|
||||
}
|
||||
static func failure(_ message: String) -> NSError { NSError(domain:"DJ XML Mapping",code:1,userInfo:[NSLocalizedDescriptionKey:message]) }
|
||||
static func normalized(_ name: String) -> String {
|
||||
|
||||
Reference in New Issue
Block a user