MIDI2CI

Discovery Module

MIDI-CI device discovery and capability inquiry with automatic lifecycle management.

CIManager

High-level actor for automatic MIDI-CI device discovery. Handles Discovery Inquiry broadcasts, response parsing, and device timeout detection.

public actor CIManager

Initialization

// Basic initialization
let transport = try CoreMIDITransport(clientName: "MyApp")
let ciManager = CIManager(transport: transport)

// With custom configuration
let config = CIManagerConfiguration(
    discoveryInterval: 10.0,
    deviceTimeout: 30.0,
    autoStartDiscovery: true
)
let ciManager = CIManager(transport: transport, configuration: config)

Properties

PropertyTypeDescription
muidMUIDThis manager's unique identifier
eventsAsyncStream<CIManagerEvent>Stream of discovery events
discoveredDevices[DiscoveredDevice]All discovered devices
peCapableDevices[DiscoveredDevice]Devices supporting Property Exchange

Methods

MethodDescription
start()Start the CI manager and begin receiving
stop()Stop the CI manager
startDiscovery()Begin periodic Discovery Inquiry broadcasts
stopDiscovery()Stop periodic broadcasts
device(for:)Get device by MUID
destination(for:)Get MIDI destination for a device
makeDestinationResolver()Create resolver closure for PEManager

Usage Example

let ciManager = CIManager(transport: transport)
try await ciManager.start()

// Listen for device events
for await event in ciManager.events {
    switch event {
    case .deviceDiscovered(let device):
        print("Found: \(device.displayName)")
        print("  MUID: \(device.muid)")
        print("  PE Support: \(device.supportsPropertyExchange)")
        
    case .deviceLost(let muid):
        print("Lost device: \(muid)")
        
    case .deviceUpdated(let device):
        print("Updated: \(device.displayName)")
        
    default:
        break
    }
}

CIManagerConfiguration

public struct CIManagerConfiguration: Sendable
PropertyTypeDefaultDescription
discoveryIntervalTimeInterval5.0Seconds between Discovery Inquiry broadcasts
deviceTimeoutTimeInterval15.0Seconds before a device is considered lost
autoStartDiscoveryBooltrueAuto-start discovery when start() is called
respondToDiscoveryBooltrueRespond to incoming Discovery Inquiries
categorySupportCategorySupport.propertyExchangeCapabilities to advertise
deviceIdentityDeviceIdentity.defaultDevice identity to advertise
maxSysExSizeUInt320Max SysEx size (0 = no limit)

CIManagerEvent

public enum CIManagerEvent: Sendable
CaseAssociated ValueDescription
deviceDiscoveredDiscoveredDeviceNew device found
deviceLostMUIDDevice timed out or invalidated
deviceUpdatedDiscoveredDeviceExisting device replied again
discoveryStartedDiscovery broadcasts started
discoveryStoppedDiscovery broadcasts stopped

DiscoveredDevice

Represents a device discovered via MIDI-CI.

public struct DiscoveredDevice: Sendable, Identifiable, Hashable
PropertyTypeDescription
muidMUIDDevice's unique identifier
identityDeviceIdentityManufacturer, family, model, version
categorySupportCategorySupportSupported MIDI-CI categories
maxSysExSizeUInt32Maximum SysEx message size
supportsPropertyExchangeBoolTrue if PE is supported
displayNameStringHuman-readable device name

CategorySupport

public struct CategorySupport: OptionSet, Sendable {
    public static let protocolNegotiation: CategorySupport
    public static let profileConfiguration: CategorySupport
    public static let propertyExchange: CategorySupport
    public static let processInquiry: CategorySupport
}

// Check device capabilities
if device.categorySupport.contains(.propertyExchange) {
    // Device supports PE
}