<commit_before>//
//  AKMIDI+Receiving.swift
//  AudioKit
//
//  Created by <NAME>, revision history on Github.
//  Copyright © 2018 AudioKit. All rights reserved.
//

internal struct MIDISources: Collection {
    typealias Index = Int
    typealias Element = MIDIEndpointRef

    init() { }

    var endIndex: Index {
        return MIDIGetNumberOfSources()
    }

    subscript (index: Index) -> Element {
        return MIDIGetSource(index)
    }
}

internal func GetMIDIObjectStringProperty(ref: MIDIObjectRef, property: CFString) -> String {
    var string: Unmanaged<CFString>?
    MIDIObjectGetStringProperty(ref, property, &string)
    if let returnString = string?.takeRetainedValue() {
        return returnString as String
    } else {
        return ""
    }
}

extension AKMIDI {

    /// Array of input names
    public var inputNames: [String] {
        return MIDISources().names
    }

    /// Add a listener to the listeners
    public func addListener(_ listener: AKMIDIListener) {
        listeners.append(listener)
    }

    /// Remove all listeners
    public func clearListeners() {
        listeners.removeAll()
    }

    /// Add a transformer to the transformers list
    public func addTransformer(_ transformer: AKMIDITransformer) {
        transformers.append(transformer)
    }

    /// Remove all transformers
    public func clearTransformers() {
        transformers.removeAll()
    }

    /// Open a MIDI Input port
    ///
    /// - parameter inputName: String containing the name of the MIDI Input
    ///
    public func openInput(_ inputName: String = "") {
        for (name, src) in zip(inputNames, MIDISources()) {
            if inputName.isEmpty || inputName == name {
                inputPorts[inputName] = MIDIPortRef()

                var port = inputPorts[inputName]!

                let result = MIDIInputPortCreateWithBlock(client, inputPortName, &port) { packetList, _ in
                    var packetCount = 1
                    for packet in packetList.pointee {
                        // a CoreMIDI packet may contain multiple MIDI events -
                        // treat it like an array of events that can be transformed
                        let events = [AKMIDIEvent](packet) //uses makeiterator
                        let transformedMIDIEventList = self.transformMIDIEventList(events)
                        // Note: incomplete sysex packets will not have a status
                        print("status is \(transformedMIDIEventList[0].status) \(transformedMIDIEventList[0].command)")
                        for transformedEvent in transformedMIDIEventList where transformedEvent.status != nil || transformedEvent.command != nil {
                            self.handleMIDIMessage(transformedEvent)
                        }
                        packetCount += 1
                    }
                }

                inputPorts[inputName] = port

                if result != noErr {
                    AKLog("Error creating MIDI Input Port : \(result)")
                }
                MIDIPortConnectSource(port, src, nil)
                endpoints[inputName] = src
            }
        }
    }

    /// Close a MIDI Input port
    ///
    /// - parameter inputName: String containing the name of the MIDI Input
    ///
    public func closeInput(_ inputName: String = "") {
        AKLog("Closing MIDI Input '\(inputName)'")
        var result = noErr
        for key in inputPorts.keys {
            if inputName.isEmpty || key == inputName {
                if let port = inputPorts[key], let endpoint = endpoints[key] {

                    result = MIDIPortDisconnectSource(port, endpoint)
                    if result == noErr {
                        endpoints.removeValue(forKey: key)
                        inputPorts.removeValue(forKey: key)
                        AKLog("Disconnected \(key) and removed it from endpoints and input ports")
                    } else {
                        AKLog("Error disconnecting MIDI port: \(result)")
                    }
                    result = MIDIPortDispose(port)
                    if result == noErr {
                        AKLog("Disposed \(key)")
                    } else {
                        AKLog("Error displosing  MIDI port: \(result)")
                    }
                }
            }
        }
    }

    /// Close all MIDI Input ports
    public func closeAllInputs() {
        AKLog("Closing All Inputs")
        closeInput()
    }

    internal func handleMIDIMessage(_ event: AKMIDIEvent) {
        for listener in listeners {
            if let type = event.status?.type {
                guard let eventChannel = event.channel else {
                    AKLog("No channel detected in handleMIDIMessage")
                    return
                }
                switch type {
                case .controllerChange:
                    listener.receivedMIDIController(event.internalData[1],
                                                    value: event.internalData[2],
                                                    channel: MIDIChannel(eventChannel))
                case .channelAftertouch:
                    listener.receivedMIDIAfterTouch(event.internalData[1],
                                                    channel: MIDIChannel(eventChannel))
                case .noteOn:
                    listener.receivedMIDINoteOn(noteNumber: MIDINoteNumber(event.internalData[1]),
                                                velocity: MIDIVelocity(event.internalData[2]),
                                                channel: MIDIChannel(eventChannel))
                case .noteOff:
                    listener.receivedMIDINoteOff(noteNumber: MIDINoteNumber(event.internalData[1]),
                                                 velocity: MIDIVelocity(event.internalData[2]),
                                                 channel: MIDIChannel(eventChannel))
                case .pitchWheel:
                    listener.receivedMIDIPitchWheel(event.pitchbendAmount!,
                                                    channel: MIDIChannel(eventChannel))
                case .polyphonicAftertouch:
                    listener.receivedMIDIAftertouch(noteNumber: MIDINoteNumber(event.internalData[1]),
                                                    pressure: event.internalData[2],
                                                    channel: MIDIChannel(eventChannel))
                case .programChange:
                    listener.receivedMIDIProgramChange(event.internalData[1],
                                                       channel: MIDIChannel(eventChannel))
                }
            }
            if let _ = event.command {
                listener.receivedMIDISystemCommand(event.internalData)
            }
            AKLog("No usable status detected in handleMIDIMessage")
            return
        }
    }<commit_msg>move error log into actual catch on recd midi<commit_after>//
//  AKMIDI+Receiving.swift
//  AudioKit
//
//  Created by <NAME>, revision history on Github.
//  Copyright © 2018 AudioKit. All rights reserved.
//

internal struct MIDISources: Collection {
    typealias Index = Int
    typealias Element = MIDIEndpointRef

    init() { }

    var endIndex: Index {
        return MIDIGetNumberOfSources()
    }

    subscript (index: Index) -> Element {
        return MIDIGetSource(index)
    }
}

internal func GetMIDIObjectStringProperty(ref: MIDIObjectRef, property: CFString) -> String {
    var string: Unmanaged<CFString>?
    MIDIObjectGetStringProperty(ref, property, &string)
    if let returnString = string?.takeRetainedValue() {
        return returnString as String
    } else {
        return ""
    }
}

extension AKMIDI {

    /// Array of input names
    public var inputNames: [String] {
        return MIDISources().names
    }

    /// Add a listener to the listeners
    public func addListener(_ listener: AKMIDIListener) {
        listeners.append(listener)
    }

    /// Remove all listeners
    public func clearListeners() {
        listeners.removeAll()
    }

    /// Add a transformer to the transformers list
    public func addTransformer(_ transformer: AKMIDITransformer) {
        transformers.append(transformer)
    }

    /// Remove all transformers
    public func clearTransformers() {
        transformers.removeAll()
    }

    /// Open a MIDI Input port
    ///
    /// - parameter inputName: String containing the name of the MIDI Input
    ///
    public func openInput(_ inputName: String = "") {
        for (name, src) in zip(inputNames, MIDISources()) {
            if inputName.isEmpty || inputName == name {
                inputPorts[inputName] = MIDIPortRef()

                var port = inputPorts[inputName]!

                let result = MIDIInputPortCreateWithBlock(client, inputPortName, &port) { packetList, _ in
                    var packetCount = 1
                    for packet in packetList.pointee {
                        // a CoreMIDI packet may contain multiple MIDI events -
                        // treat it like an array of events that can be transformed
                        let events = [AKMIDIEvent](packet) //uses makeiterator
                        let transformedMIDIEventList = self.transformMIDIEventList(events)
                        // Note: incomplete sysex packets will not have a status
                        print("status is \(transformedMIDIEventList[0].status) \(transformedMIDIEventList[0].command)")
                        for transformedEvent in transformedMIDIEventList where transformedEvent.status != nil || transformedEvent.command != nil {
                            self.handleMIDIMessage(transformedEvent)
                        }
                        packetCount += 1
                    }
                }

                inputPorts[inputName] = port

                if result != noErr {
                    AKLog("Error creating MIDI Input Port : \(result)")
                }
                MIDIPortConnectSource(port, src, nil)
                endpoints[inputName] = src
            }
        }
    }

    /// Close a MIDI Input port
    ///
    /// - parameter inputName: String containing the name of the MIDI Input
    ///
    public func closeInput(_ inputName: String = "") {
        AKLog("Closing MIDI Input '\(inputName)'")
        var result = noErr
        for key in inputPorts.keys {
            if inputName.isEmpty || key == inputName {
                if let port = inputPorts[key], let endpoint = endpoints[key] {

                    result = MIDIPortDisconnectSource(port, endpoint)
                    if result == noErr {
                        endpoints.removeValue(forKey: key)
                        inputPorts.removeValue(forKey: key)
                        AKLog("Disconnected \(key) and removed it from endpoints and input ports")
                    } else {
                        AKLog("Error disconnecting MIDI port: \(result)")
                    }
                    result = MIDIPortDispose(port)
                    if result == noErr {
                        AKLog("Disposed \(key)")
                    } else {
                        AKLog("Error displosing  MIDI port: \(result)")
                    }
                }
            }
        }
    }

    /// Close all MIDI Input ports
    public func closeAllInputs() {
        AKLog("Closing All Inputs")
        closeInput()
    }

    internal func handleMIDIMessage(_ event: AKMIDIEvent) {
        for listener in listeners {
            if let type = event.status?.type {
                guard let eventChannel = event.channel else {
                    AKLog("No channel detected in handleMIDIMessage")
                    return
                }
                switch type {
                case .controllerChange:
                    listener.receivedMIDIController(event.internalData[1],
                                                    value: event.internalData[2],
                                                    channel: MIDIChannel(eventChannel))
                case .channelAftertouch:
                    listener.receivedMIDIAfterTouch(event.internalData[1],
                                                    channel: MIDIChannel(eventChannel))
                case .noteOn:
                    listener.receivedMIDINoteOn(noteNumber: MIDINoteNumber(event.internalData[1]),
                                                velocity: MIDIVelocity(event.internalData[2]),
                                                channel: MIDIChannel(eventChannel))
                case .noteOff:
                    listener.receivedMIDINoteOff(noteNumber: MIDINoteNumber(event.internalData[1]),
                                                 velocity: MIDIVelocity(event.internalData[2]),
                                                 channel: MIDIChannel(eventChannel))
                case .pitchWheel:
                    listener.receivedMIDIPitchWheel(event.pitchbendAmount!,
                                                    channel: MIDIChannel(eventChannel))
                case .polyphonicAftertouch:
                    listener.receivedMIDIAftertouch(noteNumber: MIDINoteNumber(event.internalData[1]),
                                                    pressure: event.internalData[2],
                                                    channel: MIDIChannel(eventChannel))
                case .programChange:
                    listener.receivedMIDIProgramChange(event.internalData[1],
                                                       channel: MIDIChannel(eventChannel))
                }
            }
            if let _ = event.command {
                listener.receivedMIDISystemCommand(event.internalData)
            } else {
                AKLog("No usable status detected in handleMIDIMessage")
            }
            return
        }
    }
{'fraction_non_alphanumeric': 0.07693957811941365, 'fraction_numerical': 0.0025741866285305683, 'mean_word_length': 1.4163787145818936, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 44, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2968163', 'n_tokens_mistral': 3443, 'n_tokens_neox': 3150, 'n_words': 821}