Skip to content

Commit

Permalink
Merge pull request #36 from orchetect/dev
Browse files Browse the repository at this point in the history
API selection, fixes for packet iteration
  • Loading branch information
orchetect authored Sep 2, 2021
2 parents 9f324fd + 93654c3 commit 1eb158b
Show file tree
Hide file tree
Showing 56 changed files with 543 additions and 375 deletions.
4 changes: 3 additions & 1 deletion Docs/MIDIKit.md
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
Docs will be added in future. This is a placeholder file in the meantime.
Docs will be added in future.

In the meantime, check out the Examples folder for sample projects demonstrating usage.
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.5;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
Expand Down Expand Up @@ -280,7 +280,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.5;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ extension ContentView {

GroupBox(label: Text("MIDI Subsystem Status")) {

Text("Using "
+ (midiManager.coreMIDIVersion == .legacy ? "legacy" : "new")
+ " CoreMIDI API"
)
Text("Using " + midiManager.preferredAPI.description)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)

}
Expand Down Expand Up @@ -51,7 +48,7 @@ extension ContentView {
}
}
.frame(maxWidth: 200)
.disabled(midiManager.coreMIDIVersion == .legacy)
.disabled(midiManager.preferredAPI == .legacyCoreMIDI)

Spacer()
.frame(height: 10)
Expand Down
6 changes: 3 additions & 3 deletions Examples/MIDIEventLogger/MIDIEventLogger/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ struct ContentView: View {
try midiManager.addInput(
name: kInputName,
tag: kInputTag,
uniqueID: .none,
uniqueID: .userDefaultsManaged(key: kInputTag),
receiveHandler: .eventsLogging()
)

try midiManager.addOutput(
name: kOutputName,
tag: kOutputTag,
uniqueID: .none
uniqueID: .userDefaultsManaged(key: kOutputTag)
)
} catch {
Log.error(error)
Expand Down Expand Up @@ -87,7 +87,7 @@ struct ContentView: View {
.padding([.leading, .trailing])

.onAppear {
// wait a short delay in order to give CoreMIDI time
// wait a short delay in order to give Core MIDI time
// to set up the virtual endpoints we created in the view's init()
DispatchQueue.main
.asyncAfter(deadline: DispatchTime.now()
Expand Down
16 changes: 8 additions & 8 deletions Sources/MIDIKit/Common/Utilities/String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import Foundation
extension String {

/// Wraps a string with double-quotes (`"`)
@inlinable internal var otcQuoted: Self {
@inlinable internal var quoted: Self {

"\"\(self)\""

Expand All @@ -37,7 +37,7 @@ extension StringProtocol {
///
/// "A string 123".only(.alphanumerics)`
///
public func otcOnly(_ characterSet: CharacterSet) -> String {
public func only(_ characterSet: CharacterSet) -> String {

self.map { characterSet.contains(UnicodeScalar("\($0)")!) ? "\($0)" : "" }
.joined()
Expand All @@ -46,23 +46,23 @@ extension StringProtocol {

/// **OTCore:**
/// Returns a string preserving only characters from the passed string and removing all other characters.
public func otcOnly(characters: String) -> String {
public func only(characters: String) -> String {

self.otcOnly(CharacterSet(charactersIn: characters))
self.only(CharacterSet(charactersIn: characters))

}

/// **OTCore:**
/// Returns a string containing only alphanumeric characters and removing all other characters.
public var otcOnlyAlphanumerics: String {
public var onlyAlphanumerics: String {

self.otcOnly(.alphanumerics)
self.only(.alphanumerics)

}

/// **OTCore:**
/// Returns a string removing all characters from the passed CharacterSet.
public func otcRemoving(_ characterSet: CharacterSet) -> String {
public func removing(_ characterSet: CharacterSet) -> String {

self.components(separatedBy: characterSet)
.joined()
Expand All @@ -71,7 +71,7 @@ extension StringProtocol {

/// **OTCore:**
/// Returns a string removing all characters from the passed string.
public func otcRemoving(characters: String) -> String {
public func removing(characters: String) -> String {

self.components(separatedBy: CharacterSet(charactersIn: characters))
.joined()
Expand Down
92 changes: 92 additions & 0 deletions Sources/MIDIKit/IO/API/APIVersion.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//
// APIVersion.swift
// MIDIKit • https://github.com/orchetect/MIDIKit
//

import Darwin

extension MIDI.IO {

/// Enum describing which underlying Core MIDI API is being used internally.
public enum APIVersion {

/// Legacy Core MIDI API first introduced in early versions of OSX.
///
/// Internally using `MIDIPacketList` / `MIDIPacket`.
case legacyCoreMIDI

/// New Core MIDI API introduced in macOS 11, iOS 14, macCatalyst 14, tvOS 14, and watchOS 7.
///
/// Internally using `MIDIEventList` / `MIDIEventPacket`.
case newCoreMIDI

}

}

extension MIDI.IO.APIVersion {

/// Returns the recommended API version for the current platform (operating system).
public static func bestForPlatform() -> Self {

if #available(macOS 11, iOS 14, macCatalyst 14, tvOS 14, watchOS 7, *) {
// return legacy for now, since new API is buggy;
// in future, this should return .newCoreMIDI when new API is more stable
return .legacyCoreMIDI

} else {
return .legacyCoreMIDI
}

}

}

extension MIDI.IO.APIVersion {

/// Returns true if API version can be used on the current platform (operating system).
public var isValidOnCurrentPlatform: Bool {

switch self {
case .legacyCoreMIDI:
#if os(macOS)
if #available(macOS 12, *) { return false }
return true
#elseif os(iOS)
if #available(iOS 15, *) { return false }
return true
#elseif os(tvOS) || os(watchOS)
// only new API is supported on tvOS and watchOS
return false
#else
// future or unknown/unsupported platform
return false
#endif

case .newCoreMIDI:
if #available(macOS 11, iOS 14, macCatalyst 14, tvOS 14, watchOS 7, *) {
return true
}

return false
}

}

}

extension MIDI.IO.APIVersion: CustomStringConvertible {

public var description: String {

switch self {
case .legacyCoreMIDI:
return "Legacy Core MIDI API"

case .newCoreMIDI:
return "New Core MIDI API"
}

}

}
23 changes: 0 additions & 23 deletions Sources/MIDIKit/IO/API/CoreMIDIVersion.swift

This file was deleted.

4 changes: 2 additions & 2 deletions Sources/MIDIKit/IO/API/ProtocolVersion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
// MIDIKit • https://github.com/orchetect/MIDIKit
//

extension MIDI {
extension MIDI.IO {

#warning("> this is currently unused")

/// Enum describing which underlying CoreMIDI API is being used internally.
/// MIDI protocol version.
public enum ProtocolVersion {

/// MIDI 1.0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//
// CoreMIDI Connections.swift
// Core MIDI Connections.swift
// MIDIKit • https://github.com/orchetect/MIDIKit
//

import CoreMIDI

extension MIDI.IO {

/// Queries CoreMIDI for existing persistent play-thru connections stored in the system matching the specified persistent owner ID.
/// Queries Core MIDI for existing persistent play-thru connections stored in the system matching the specified persistent owner ID.
///
/// To delete them all, see sister function `removeAllSystemThruConnectionsPersistentEntries(:)`.
///
Expand Down Expand Up @@ -52,7 +52,7 @@ extension MIDI.IO {

}

/// Deletes all system-held CoreMIDI MIDI play-thru connections matching an owner ID.
/// Deletes all system-held Core MIDI MIDI play-thru connections matching an owner ID.
///
/// - Parameter persistentOwnerID: reverse-DNS domain that was used when the connection was first made
///
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// CoreMIDI Devices.swift
// Core MIDI Devices.swift
// MIDIKit • https://github.com/orchetect/MIDIKit
//

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// CoreMIDI Endpoints.swift
// Core MIDI Endpoints.swift
// MIDIKit • https://github.com/orchetect/MIDIKit
//

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// CoreMIDI Entities.swift
// Core MIDI Entities.swift
// MIDIKit • https://github.com/orchetect/MIDIKit
//

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// CoreMIDI Properties Get.swift
// Core MIDI Properties Get.swift
// MIDIKit • https://github.com/orchetect/MIDIKit
//

Expand All @@ -9,7 +9,7 @@ extension MIDI.IO {

// MARK: - Property Readers

/// Retrieves the entire properties dictionary as the CoreMIDI-native `CFPropertyList`.
/// Retrieves the entire properties dictionary as the Core MIDI-native `CFPropertyList`.
///
/// - Parameter deep: Returns nested results for all children if `True`.
/// - Throws: `MIDI.IO.MIDIError`
Expand Down Expand Up @@ -83,7 +83,7 @@ extension MIDI.IO {
guard let unwrappedVal = val?.takeRetainedValue() else {
val?.release()
throw MIDI.IO.MIDIError.readError(
"Got nil while reading MIDIEndpointRef property value \((forProperty as String).otcQuoted)"
"Got nil while reading MIDIEndpointRef property value \((forProperty as String).quoted)"
)
}

Expand Down Expand Up @@ -514,7 +514,7 @@ extension MIDI.IO {
// / / Entity
// / / / Endpoint
// / / / /
// *|D|E|E| CoreMIDI Constant value type
// *|D|E|E| Core MIDI Constant value type
// -|-|-|-|------------------------------------------- ----------
// | | | | Identification:
// *|•|•|•| kMIDIPropertyName string
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// CoreMIDI Properties Set.swift
// Core MIDI Properties Set.swift
// MIDIKit • https://github.com/orchetect/MIDIKit
//

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,38 @@ import CoreMIDI

extension UnsafePointer where Pointee == MIDIEventList {

/// MIDIKit backwards-compatible implementation of CoreMIDI's `MIDIPacketList.UnsafeSequence`
/// MIDIKit sequence on `UnsafePointer<MIDIEventList>` to return `[MIDIEventPacket]`
@available(macOS 11, iOS 14, macCatalyst 14, tvOS 14, watchOS 7, *)
public func mkUnsafeSequence() -> MIDIEventList.MKUnsafeSequence {
public func mkSequence() -> MIDIEventList.MKSequence {

MIDIEventList.MKUnsafeSequence(self)
MIDIEventList.MKSequence(self)

}

}

extension MIDIEventList {

/// MIDIKit backwards-compatible implementation of CoreMIDI's `MIDIEventList.UnsafeSequence`
/// MIDIKit sequence on `UnsafePointer<MIDIEventList>` to return `[MIDIEventPacket]`
@available(macOS 11, iOS 14, macCatalyst 14, tvOS 14, watchOS 7, *)
public struct MKUnsafeSequence: Sequence {
public struct MKSequence: Sequence {

public typealias Element = UnsafePointer<MIDIEventPacket>
public typealias Element = MIDIEventPacket

internal var pointers: [UnsafePointer<MIDIEventPacket>] = []
internal var packets: [MIDIEventPacket] = []

public init(_ midiPacketListPtr: UnsafePointer<MIDIEventList>) {

CMIDIEventListIterate(midiPacketListPtr) {
guard let unwrappedPtr = $0 else { return }
pointers.append(unwrappedPtr)
if let packet = $0?.pointee {
packets.append(packet)
}
}

}

public func makeIterator() -> Iterator {
Iterator(pointers)
Iterator(packets)
}

public struct Iterator: IteratorProtocol {
Expand Down
Loading

0 comments on commit 1eb158b

Please sign in to comment.