diff --git a/Examples/Example Mac/ViewController.swift b/Examples/Example Mac/ViewController.swift index 72c0ec8..70c3a2a 100644 --- a/Examples/Example Mac/ViewController.swift +++ b/Examples/Example Mac/ViewController.swift @@ -16,8 +16,8 @@ class ViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() - let chord = Chord(type: .maj, key: .e) - let firstPosition = chord.notes(octaves: fretboardView?.fretboard.octaves ?? [2, 3, 4]) + let chord = Chord(type: ChordType(third: .major), key: Key(type: .e)) + let firstPosition = chord.pitches(octaves: fretboardView?.fretboard.octaves ?? [2, 3, 4]) fretboardView?.fretboard.direction = .vertical fretboardView?.fretboard.startIndex = 0 fretboardView?.isChordModeOn = true diff --git a/Examples/Example TV/AppDelegate.swift b/Examples/Example TV/AppDelegate.swift index c5aa3f6..e73651d 100644 --- a/Examples/Example TV/AppDelegate.swift +++ b/Examples/Example TV/AppDelegate.swift @@ -13,8 +13,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { // Override point for customization after application launch. return true } diff --git a/Examples/Example TV/ViewController.swift b/Examples/Example TV/ViewController.swift index 8371ba1..e2358e6 100644 --- a/Examples/Example TV/ViewController.swift +++ b/Examples/Example TV/ViewController.swift @@ -17,7 +17,7 @@ class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - let chord = Chord(type: .maj, key: .a) + let chord = Chord(type: ChordType(third: .major), key: Key(type: .a)) verticalFretboard?.fretboard.direction = .vertical verticalFretboard?.fretboard.select(chord: chord) diff --git a/Examples/Example iOS/AppDelegate.swift b/Examples/Example iOS/AppDelegate.swift index e4cd5df..7861a6c 100644 --- a/Examples/Example iOS/AppDelegate.swift +++ b/Examples/Example iOS/AppDelegate.swift @@ -13,8 +13,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { // Override point for customization after application launch. return true } diff --git a/Examples/Example iOS/Base.lproj/Main.storyboard b/Examples/Example iOS/Base.lproj/Main.storyboard index 0ee381b..dfd8360 100644 --- a/Examples/Example iOS/Base.lproj/Main.storyboard +++ b/Examples/Example iOS/Base.lproj/Main.storyboard @@ -1,10 +1,11 @@ - + - + + diff --git a/Examples/Example iOS/ViewController.swift b/Examples/Example iOS/ViewController.swift index 22100ea..b779ff5 100644 --- a/Examples/Example iOS/ViewController.swift +++ b/Examples/Example iOS/ViewController.swift @@ -20,7 +20,7 @@ class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - let chord = Chord(type: .maj, key: .a) + let chord = Chord(type: ChordType(third: .major), key: Key(type: .a)) fretboardView?.fretboard.select(chord: chord) } } diff --git a/Fretboard.podspec b/Fretboard.podspec index b90486d..2b213c5 100644 --- a/Fretboard.podspec +++ b/Fretboard.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "Fretboard" - s.version = "0.0.1" + s.version = "0.0.2" s.summary = "Customisable guitar fretboard view for iOS, tvOS and macOS with CoreGraphics" # This description is used to generate tags and improve search results. @@ -54,7 +54,7 @@ Demo Requierments ---- -* Swift 3.0+ +* Swift 4.0+ * iOS 8.0+ * tvOS 9.0+ * macOS 10.9+ diff --git a/Fretboard.xcodeproj/project.pbxproj b/Fretboard.xcodeproj/project.pbxproj index f8c1998..99cb21f 100644 --- a/Fretboard.xcodeproj/project.pbxproj +++ b/Fretboard.xcodeproj/project.pbxproj @@ -39,6 +39,9 @@ B28B04781E9A969D006C0CED /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B28B04591E9A9658006C0CED /* Assets.xcassets */; }; B28B04791E9A969E006C0CED /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B28B045A1E9A9658006C0CED /* LaunchScreen.storyboard */; }; B28B047A1E9A96A0006C0CED /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B28B045C1E9A9658006C0CED /* Main.storyboard */; }; + B2D0B4C92154DE1900E4DFD7 /* FretboardScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2D0B4C82154DE1900E4DFD7 /* FretboardScrollView.swift */; }; + B2D0B4CA2154DE1900E4DFD7 /* FretboardScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2D0B4C82154DE1900E4DFD7 /* FretboardScrollView.swift */; }; + B2D0B4CB2154DE1900E4DFD7 /* FretboardScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2D0B4C82154DE1900E4DFD7 /* FretboardScrollView.swift */; }; D2F29B65DEB509111D543C9E /* Pods_Fretboard_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EE1048B0E93B04B96E13499 /* Pods_Fretboard_iOS.framework */; }; F8697A7B76693342D7830FBC /* Pods_Example_Mac.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E0E35D1BD9606D4C54A376DC /* Pods_Example_Mac.framework */; }; /* End PBXBuildFile section */ @@ -85,6 +88,7 @@ B28B046B1E9A9658006C0CED /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; B28B046C1E9A9658006C0CED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B28B046D1E9A9658006C0CED /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + B2D0B4C82154DE1900E4DFD7 /* FretboardScrollView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FretboardScrollView.swift; sourceTree = ""; }; BD0DD0687CE8C78F7F66F2D4 /* Pods-Example Mac.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example Mac.release.xcconfig"; path = "Pods/Target Support Files/Pods-Example Mac/Pods-Example Mac.release.xcconfig"; sourceTree = ""; }; D0D7A4DA19AD9AD119667CDF /* Pods-Example TV.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example TV.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Example TV/Pods-Example TV.debug.xcconfig"; sourceTree = ""; }; D6F32412D92AD97B87B045EB /* Pods-Example iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Example iOS/Pods-Example iOS.debug.xcconfig"; sourceTree = ""; }; @@ -208,6 +212,7 @@ B22BFC481E9A9329005130EE /* Fretboard.swift */, B21502E11EA9415600018B87 /* FretboardTuning.swift */, B21502E51EA9416300018B87 /* FretboardView.swift */, + B2D0B4C82154DE1900E4DFD7 /* FretboardScrollView.swift */, B21502E91EA9417500018B87 /* Extensions.swift */, B22BFC411E9A9304005130EE /* Fretboard.h */, B22BFC421E9A9304005130EE /* Info iOS.plist */, @@ -303,7 +308,6 @@ B22BFC191E9A927D005130EE /* Frameworks */, B22BFC1A1E9A927D005130EE /* Headers */, B22BFC1B1E9A927D005130EE /* Resources */, - BFB353C01AD5E7DCDE0686FF /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -323,7 +327,6 @@ B22BFC271E9A9290005130EE /* Frameworks */, B22BFC281E9A9290005130EE /* Headers */, B22BFC291E9A9290005130EE /* Resources */, - 1368A35EA246A6FC7BCC51DB /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -343,7 +346,6 @@ B22BFC341E9A929A005130EE /* Frameworks */, B22BFC351E9A929A005130EE /* Headers */, B22BFC361E9A929A005130EE /* Resources */, - B4AB68BD089475A65C65B631 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -363,7 +365,6 @@ B28B041B1E9A962E006C0CED /* Frameworks */, B28B041C1E9A962E006C0CED /* Resources */, CF4421D33594839BA30371A4 /* [CP] Embed Pods Frameworks */, - 740846165C2941A5308023E7 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -383,7 +384,6 @@ B28B04311E9A9638006C0CED /* Frameworks */, B28B04321E9A9638006C0CED /* Resources */, D7E12B74B1C1935FF767D7A1 /* [CP] Embed Pods Frameworks */, - C6B6996AC6D1484951478604 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -403,7 +403,6 @@ B28B04441E9A9641006C0CED /* Frameworks */, B28B04451E9A9641006C0CED /* Resources */, 0B98929C6CBCB150A73D9F5E /* [CP] Embed Pods Frameworks */, - 1CE57C40680E0F664BD34E7E /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -421,7 +420,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0830; - LastUpgradeCheck = 0830; + LastUpgradeCheck = 1000; TargetAttributes = { B22BFC1C1E9A927D005130EE = { CreatedOnToolsVersion = 8.3; @@ -538,43 +537,20 @@ files = ( ); inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Example Mac/Pods-Example Mac-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/CenterTextLayer-macOS10.10/CenterTextLayer.framework", + "${BUILT_PRODUCTS_DIR}/MusicTheorySwift-macOS10.10/MusicTheorySwift.framework", + "${BUILT_PRODUCTS_DIR}/Fretboard-macOS/Fretboard.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CenterTextLayer.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MusicTheorySwift.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Fretboard.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example Mac/Pods-Example Mac-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 1368A35EA246A6FC7BCC51DB /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Fretboard TV/Pods-Fretboard TV-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - 1CE57C40680E0F664BD34E7E /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example Mac/Pods-Example Mac-resources.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Example Mac/Pods-Example Mac-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 1EC5E361C10FE0ED0F548D1F /* [CP] Check Pods Manifest.lock */ = { @@ -583,13 +559,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Example TV-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 32CD6E7259A728E9D8F28328 /* [CP] Check Pods Manifest.lock */ = { @@ -598,13 +577,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Example iOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 71A9C0DD7816BF026356097E /* [CP] Check Pods Manifest.lock */ = { @@ -613,28 +595,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Fretboard iOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; - 740846165C2941A5308023E7 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example iOS/Pods-Example iOS-resources.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 857DAB288BE91F7FD4D886C9 /* [CP] Check Pods Manifest.lock */ = { @@ -643,43 +613,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Fretboard Mac-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; - B4AB68BD089475A65C65B631 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Fretboard Mac/Pods-Fretboard Mac-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - BFB353C01AD5E7DCDE0686FF /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Fretboard iOS/Pods-Fretboard iOS-resources.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; C53DAB8FC1DCE81F181ED591 /* [CP] Check Pods Manifest.lock */ = { @@ -688,28 +631,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Example Mac-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; - C6B6996AC6D1484951478604 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example TV/Pods-Example TV-resources.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; CF4421D33594839BA30371A4 /* [CP] Embed Pods Frameworks */ = { @@ -718,13 +649,20 @@ files = ( ); inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Example iOS/Pods-Example iOS-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/CenterTextLayer-iOS9.0/CenterTextLayer.framework", + "${BUILT_PRODUCTS_DIR}/MusicTheorySwift-iOS9.0/MusicTheorySwift.framework", + "${BUILT_PRODUCTS_DIR}/Fretboard-iOS/Fretboard.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CenterTextLayer.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MusicTheorySwift.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Fretboard.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example iOS/Pods-Example iOS-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Example iOS/Pods-Example iOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; D7E12B74B1C1935FF767D7A1 /* [CP] Embed Pods Frameworks */ = { @@ -733,13 +671,20 @@ files = ( ); inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Example TV/Pods-Example TV-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/CenterTextLayer-tvOS9.0/CenterTextLayer.framework", + "${BUILT_PRODUCTS_DIR}/MusicTheorySwift-tvOS9.0/MusicTheorySwift.framework", + "${BUILT_PRODUCTS_DIR}/Fretboard-tvOS/Fretboard.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CenterTextLayer.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MusicTheorySwift.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Fretboard.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example TV/Pods-Example TV-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Example TV/Pods-Example TV-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; FD49DEB51B4EB6404A2D9B18 /* [CP] Check Pods Manifest.lock */ = { @@ -748,13 +693,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Fretboard TV-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -764,6 +712,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + B2D0B4C92154DE1900E4DFD7 /* FretboardScrollView.swift in Sources */, B21502E21EA9415600018B87 /* FretboardTuning.swift in Sources */, B22BFC491E9A9329005130EE /* Fretboard.swift in Sources */, B21502E61EA9416300018B87 /* FretboardView.swift in Sources */, @@ -775,6 +724,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + B2D0B4CA2154DE1900E4DFD7 /* FretboardScrollView.swift in Sources */, B21502E31EA9415600018B87 /* FretboardTuning.swift in Sources */, B22BFC4A1E9A939E005130EE /* Fretboard.swift in Sources */, B21502E71EA9416300018B87 /* FretboardView.swift in Sources */, @@ -786,6 +736,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + B2D0B4CB2154DE1900E4DFD7 /* FretboardScrollView.swift in Sources */, B21502E41EA9415600018B87 /* FretboardTuning.swift in Sources */, B22BFC4B1E9A939F005130EE /* Fretboard.swift in Sources */, B21502E81EA9416300018B87 /* FretboardView.swift in Sources */, @@ -861,12 +812,64 @@ B22BFC161E9A9269005130EE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; B22BFC171E9A9269005130EE /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; }; name = Release; }; @@ -931,7 +934,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -991,7 +994,7 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -1058,7 +1061,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; VERSIONING_SYSTEM = "apple-generic"; @@ -1117,7 +1120,7 @@ SDKROOT = appletvos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; VALIDATE_PRODUCT = YES; @@ -1188,7 +1191,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -1248,7 +1251,7 @@ SDKROOT = macosx; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -1308,7 +1311,7 @@ SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -1359,7 +1362,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -1418,7 +1421,7 @@ SDKROOT = appletvos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; }; @@ -1469,7 +1472,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; VALIDATE_PRODUCT = YES; @@ -1531,7 +1534,7 @@ SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -1582,7 +1585,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; }; name = Release; }; diff --git a/Fretboard.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Fretboard.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Fretboard.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Podfile b/Podfile index 4444d25..fbfa8b2 100644 --- a/Podfile +++ b/Podfile @@ -1,5 +1,6 @@ # Uncomment the next line to define a global platform for your project # platform :ios, '9.0' +swift_version="4.2" target 'Fretboard iOS' do use_frameworks! @@ -34,8 +35,8 @@ target 'Example TV' do pod 'Fretboard', :path => '.' end -post_install do |installer| - installer.pods_project.build_configurations.each do |config| - config.build_settings['LD_RUNPATH_SEARCH_PATHS'] = ['$(FRAMEWORK_SEARCH_PATHS)'] - end -end +#post_install do |installer| +# installer.pods_project.build_configurations.each do |config| +# config.build_settings['LD_RUNPATH_SEARCH_PATHS'] = ['$(FRAMEWORK_SEARCH_PATHS)'] +# end +#end diff --git a/Podfile.lock b/Podfile.lock index b3833e9..dbfb542 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,24 +1,29 @@ PODS: - - CenterTextLayer (0.0.1) + - CenterTextLayer (0.0.2) - Fretboard (0.0.1): - CenterTextLayer - MusicTheorySwift - - MusicTheorySwift (0.0.4) + - MusicTheorySwift (1.1.0) DEPENDENCIES: - CenterTextLayer - Fretboard (from `.`) - MusicTheorySwift +SPEC REPOS: + https://github.com/cocoapods/specs.git: + - CenterTextLayer + - MusicTheorySwift + EXTERNAL SOURCES: Fretboard: :path: "." SPEC CHECKSUMS: - CenterTextLayer: 8ba737f794769c3bd0e3f28706b9edf6f787fbb7 - Fretboard: 52ffccd4b5dde4428faf24c9ec0eca93cebb167e - MusicTheorySwift: 213563918695d0a2fa37a805a0ad63b090a12bfe + CenterTextLayer: 7fe5dab46ba3372c527f09a518a84f8be4a89e38 + Fretboard: a98553977498e9a8629b0868c166ee2e7e984d32 + MusicTheorySwift: 555d61fc174c36c7cb1a41cf20b54628ba6b3e32 -PODFILE CHECKSUM: 3dcd1672aaf5baed9a47f386522228bed9ac645a +PODFILE CHECKSUM: 77ea5853003049ea9ee9a7142d1a75d5b1974978 -COCOAPODS: 1.2.1.beta.1 +COCOAPODS: 1.6.0.beta.1 diff --git a/README.md b/README.md index abd34fb..456d5a3 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Demo Requierments ---- -* Swift 3.0+ +* Swift 4.0+ * iOS 8.0+ * tvOS 9.0+ * macOS 10.9+ @@ -51,13 +51,13 @@ Fretboard uses [`MusicTheory`](https://github.com/cemolcay/MusicTheory) library You need to select/unselect notes, chords or scales on `fretboard` property of your `FretboardView` instance. ``` swift -let chord = Chord(type: .maj, key: .a) +let chord = Chord(type: ChordType(third: .major), key: Key(type: .a)) fretboardView?.fretboard.select(chord: chord) -let scale = Scale(type: .major, key: .e) +let scale = Scale(type: .major, key: Key(type: .e, accidental: .flat)) fretboardView?.fretboard.select(scale: scale) -let note = Note(type: .a, octave: 2) +let note = Pitch(key: Key(type: .a), octave: 2) fretboardView?.fretboard.select(note: note) fretboardView?.fretboard.unselect(note: note) @@ -76,10 +76,10 @@ Also, you can define custom tunings with `CustomTuning` struct with custom strin ``` swift let tuning = CustomTuning( strings: [ - Note(type: .g, octave: 2), - Note(type: .d, octave: 2), - Note(type: .a, octave: 1), - Note(type: .e, octave: 1) + Pitch(key: Key(type: .g), octave: 2), + Pitch(key: Key(type: .d), octave: 2), + Pitch(key: Key(type: .a), octave: 1), + Pitch(key: Key(type: .e), octave: 1) ], description: "My Custom Tuning") fretboardView?.fretboard.tuning = tuning @@ -108,6 +108,17 @@ Rendering note names on pressed notes and optional. Also rendering fret numbers and strings names are optional too. See the properties of `FretboardView`. +### FretboardScrollView + +There is also a scroll view you can use in your iOS/tvOS/macOS apps that you can scroll your fretboard inside it. It has a `FretboardView` instance you can customise your fretboard directly. + +``` swift +@IBOutlet weak var scrollView: FretboardScrollView? +scrollView?.fretboardView.fretStartIndex = appState.fretStartIndex +scrollView?.fretboardView.fretCount = appState.fretCount +scrollView?.fretboardView.fretboard.tuning = appState.tuning.tuning +``` + FretBud ---- diff --git a/Source/Extensions.swift b/Source/Extensions.swift index 31161e1..c14d392 100644 --- a/Source/Extensions.swift +++ b/Source/Extensions.swift @@ -33,13 +33,13 @@ for i in 0 ..< self.elementCount { let type = self.element(at: i, associatedPoints: &points) switch type { - case .moveToBezierPathElement: + case .moveTo: path.move(to: points[0]) - case .lineToBezierPathElement: + case .lineTo: path.addLine(to: points[0]) - case .curveToBezierPathElement: + case .curveTo: path.addCurve(to: points[2], control1: points[0], control2: points[1]) - case .closePathBezierPathElement: + case .closePath: path.closeSubpath() } } @@ -55,7 +55,7 @@ extension Collection where Indices.Iterator.Element == Index { /// Returns the element at the specified index iff it is within bounds, otherwise nil. - subscript (safe index: Index) -> Generator.Element? { + subscript (safe index: Index) -> Iterator.Element? { return indices.contains(index) ? self[index] : nil } } diff --git a/Source/Fretboard.swift b/Source/Fretboard.swift index 5ce4f1a..e1b03ac 100644 --- a/Source/Fretboard.swift +++ b/Source/Fretboard.swift @@ -31,7 +31,7 @@ public func ==(left: FretboardNote?, right: FretboardNote?) -> Bool { /// Describes a note in fretboard. public class FretboardNote { /// Note that fretboard has. - public var note: Note + public var note: Pitch /// Index of fret on fretboard. public var fretIndex: Int @@ -45,7 +45,7 @@ public class FretboardNote { /// Initilizes with note value. /// /// - Parameter note: Note on fretboard. - public init(note: Note, fretIndex: Int, stringIndex: Int) { + public init(note: Pitch, fretIndex: Int, stringIndex: Int) { self.note = note self.fretIndex = fretIndex self.stringIndex = stringIndex @@ -165,13 +165,13 @@ public class Fretboard { /// Returns tuned strings by its direction. /// Left to right higher pitches in vertical direction. /// Bottom to top higer pitches in horizontal direction. - var strings: [Note] { + var strings: [Pitch] { return direction == .horizontal ? tuning.strings.reversed() : tuning.strings } /// Returns sorted octave range in fretboard. public var octaves: [Int] { - return Set(notes.flatMap({ $0 }).map({ $0.note.octave })).sorted() + return Set(notes.compactMap({ $0 }).map({ $0.note.octave })).sorted() } // MARK: Note Selection @@ -179,7 +179,7 @@ public class Fretboard { /// Marks selected the notes in fretboard. /// /// - Parameter note: To be selected note in fretboard. - public func select(note: Note) { + public func select(note: Pitch) { notes.filter({ $0.note == note }).forEach({ $0.isSelected = true }) delegate?.fretboad(self, didSelectedNotesChange: notes) } @@ -187,7 +187,7 @@ public class Fretboard { /// Marks the notes selected in fretboard /// /// - Parameter notes: Notes to be selected. - public func select(notes: [Note]) { + public func select(notes: [Pitch]) { let hasNote: (FretboardNote) -> Bool = { fret in return notes.contains(where: { $0 == fret.note }) } @@ -200,8 +200,8 @@ public class Fretboard { /// /// - Parameter chord: To be selected notes of chord in fretboard. public func select(chord: Chord) { - let notes = chord.notes(octaves: octaves) - let hasNote: (Note) -> Bool = { note in + let notes = chord.pitches(octaves: octaves) + let hasNote: (Pitch) -> Bool = { note in return notes.contains(where: { $0 == note }) } @@ -213,8 +213,8 @@ public class Fretboard { /// /// - Parameter scale: To be selected notes of scale in fretboard. public func select(scale: Scale) { - let notes = scale.notes(octaves: octaves) - let hasNote: (Note) -> Bool = { note in + let notes = scale.pitches(octaves: octaves) + let hasNote: (Pitch) -> Bool = { note in return notes.contains(where: { $0 == note }) } @@ -225,7 +225,7 @@ public class Fretboard { /// Marks unselect the notes in fretboard if its already selected. /// /// - Parameter note: To be unselected note in fretboard. - public func unselect(note: Note) { + public func unselect(note: Pitch) { notes.filter({ $0.note == note }).forEach({ $0.isSelected = false }) delegate?.fretboad(self, didSelectedNotesChange: notes) } diff --git a/Source/FretboardScrollView.swift b/Source/FretboardScrollView.swift new file mode 100644 index 0000000..4008893 --- /dev/null +++ b/Source/FretboardScrollView.swift @@ -0,0 +1,125 @@ +// +// FretboardScrollView.swift +// FretBud +// +// Created by Cem Olcay on 01/05/2017. +// +// + +#if os(iOS) || os(tvOS) + import UIKit +#elseif os(OSX) + import AppKit +#endif + +#if os(iOS) || os(tvOS) + typealias FRScrollView = UIScrollView +#elseif os(OSX) + typealias FRScrollView = NSScrollView +#endif + +@IBDesignable +class FretboardScrollView: FRScrollView { + @IBInspectable var fretboardView = FretboardView(frame: .zero) { didSet { updateLayout() }} + @IBInspectable var aspectRatio: CGFloat = 0.225 { didSet { updateLayout() }} + + // MARK: Init + + #if os(iOS) || os(tvOS) + override init(frame: CGRect) { + super.init(frame: frame) + commonInit() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + commonInit() + } + #elseif os(OSX) + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + commonInit() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + commonInit() + } + #endif + + private func commonInit() { + #if os(iOS) || os(tvOS) + addSubview(fretboardView) + #if os(tvOS) + panGestureRecognizer.allowedTouchTypes = [NSNumber(integerLiteral: UITouch.TouchType.indirect.rawValue)] + #endif + #elseif os(OSX) + documentView?.addSubview(fretboardView) + #endif + } + + // MARK: Lifecycle + + #if os(tvOS) + override var canBecomeFocused: Bool { + return true + } + + override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) { + super.didUpdateFocus(in: context, with: coordinator) + if context.nextFocusedView == self { + layer.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.4).cgColor + layer.cornerRadius = 10 + layer.masksToBounds = true + } else if context.previouslyFocusedView == self { + layer.backgroundColor = UIColor.clear.cgColor + } + } + #endif + + // MARK: Layout + + #if os(iOS) || os(tvOS) + override func layoutSubviews() { + super.layoutSubviews() + layoutFretboard() + } + #elseif os(OSX) + override func layout() { + super.layout() + layoutFretboard() + } + #endif + + private func updateLayout() { + #if os(iOS) || os(tvOS) + setNeedsLayout() + #elseif os(OSX) + needsLayout = true + #endif + } + + private func layoutFretboard() { + let fretCount = CGFloat(fretboardView.fretboard.count) + #if os(iOS) || os(tvOS) + let width = frame.size.width + let height = frame.size.height + #elseif os(OSX) + let width = contentView.frame.size.width + let height = contentView.frame.size.height + #endif + switch fretboardView.fretboard.direction { + case .horizontal: + let fretSize = frame.size.height * aspectRatio + fretboardView.frame = CGRect(x: 0, y: 0, width: fretSize * fretCount, height: height) + case .vertical: + let fretSize = frame.size.width * aspectRatio + fretboardView.frame = CGRect(x: 0, y: 0, width: width, height: fretSize * fretCount) + } + #if os(iOS) || os(tvOS) + contentSize = fretboardView.frame.size + #elseif os(OSX) + documentView?.frame.size = fretboardView.frame.size + #endif + } +} diff --git a/Source/FretboardTuning.swift b/Source/FretboardTuning.swift index 6c1e446..33126bd 100644 --- a/Source/FretboardTuning.swift +++ b/Source/FretboardTuning.swift @@ -7,9 +7,9 @@ // #if os(iOS) || os(tvOS) - import UIKit +import UIKit #elseif os(OSX) - import AppKit +import AppKit #endif import MusicTheorySwift @@ -19,7 +19,7 @@ import MusicTheorySwift public protocol FretboardTuning: CustomStringConvertible { /// Open position notes of strings on fretboard. From top to down in horizontal fashion. - var strings: [Note] { get } + var strings: [Pitch] { get } } // MARK: - GuitarTuning @@ -86,537 +86,537 @@ public enum GuitarTuning: FretboardTuning { case mandoguitar case rustyCage - public var strings: [Note] { + public var strings: [Pitch] { switch self { case .standard: return [ - Note(type: .e, octave: 2), - Note(type: .a, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .b, octave: 3), - Note(type: .e, octave: 4) + Pitch(key: Key(type: .e, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4) ] case .dropD: return [ - Note(type: .d, octave: 2), - Note(type: .a, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .b, octave: 3), - Note(type: .e, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4) ] case .halfStepDown: return [ - Note(type: .eFlat, octave: 2), - Note(type: .aFlat, octave: 2), - Note(type: .dFlat, octave: 3), - Note(type: .gFlat, octave: 3), - Note(type: .bFlat, octave: 3), - Note(type: .eFlat, octave: 4) + Pitch(key: Key(type: .e, accidental: .flat), octave: 2), + Pitch(key: Key(type: .a, accidental: .flat), octave: 2), + Pitch(key: Key(type: .d, accidental: .flat), octave: 3), + Pitch(key: Key(type: .g, accidental: .flat), octave: 3), + Pitch(key: Key(type: .b, accidental: .flat), octave: 3), + Pitch(key: Key(type: .e, accidental: .flat), octave: 4) ] case .fullStepDown: return [ - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), - Note(type: .c, octave: 3), - Note(type: .f, octave: 3), - Note(type: .a, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .f, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .oneAndHalfStepDown: return [ - Note(type: .dFlat, octave: 2), - Note(type: .gFlat, octave: 2), - Note(type: .b, octave: 2), - Note(type: .e, octave: 3), - Note(type: .aFlat, octave: 3), - Note(type: .dFlat, octave: 4) + Pitch(key: Key(type: .d, accidental: .flat), octave: 2), + Pitch(key: Key(type: .g, accidental: .flat), octave: 2), + Pitch(key: Key(type: .b, accidental: .natural), octave: 2), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .flat), octave: 3), + Pitch(key: Key(type: .d, accidental: .flat), octave: 4) ] case .doubleDropD: return [ - Note(type: .d, octave: 2), - Note(type: .a, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .b, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .dropC: return [ - Note(type: .c, octave: 2), - Note(type: .g, octave: 2), - Note(type: .c, octave: 3), - Note(type: .f, octave: 3), - Note(type: .a, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .f, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .dropDFlat: return [ - Note(type: .dFlat, octave: 2), - Note(type: .aFlat, octave: 2), - Note(type: .dFlat, octave: 3), - Note(type: .gFlat, octave: 3), - Note(type: .bFlat, octave: 3), - Note(type: .eFlat, octave: 4) + Pitch(key: Key(type: .d, accidental: .flat), octave: 2), + Pitch(key: Key(type: .a, accidental: .flat), octave: 2), + Pitch(key: Key(type: .d, accidental: .flat), octave: 3), + Pitch(key: Key(type: .g, accidental: .flat), octave: 3), + Pitch(key: Key(type: .b, accidental: .flat), octave: 3), + Pitch(key: Key(type: .e, accidental: .flat), octave: 4) ] case .dropB: return [ - Note(type: .b, octave: 1), - Note(type: .gFlat, octave: 2), - Note(type: .b, octave: 2), - Note(type: .e, octave: 3), - Note(type: .aFlat, octave: 3), - Note(type: .dFlat, octave: 4) + Pitch(key: Key(type: .b, accidental: .natural), octave: 1), + Pitch(key: Key(type: .g, accidental: .flat), octave: 2), + Pitch(key: Key(type: .b, accidental: .natural), octave: 2), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .flat), octave: 3), + Pitch(key: Key(type: .d, accidental: .flat), octave: 4) ] case .dropBFlat: return [ - Note(type: .bFlat, octave: 1), - Note(type: .f, octave: 2), - Note(type: .bFlat, octave: 2), - Note(type: .eFlat, octave: 3), - Note(type: .g, octave: 3), - Note(type: .c, octave: 4) + Pitch(key: Key(type: .b, accidental: .flat), octave: 1), + Pitch(key: Key(type: .f, accidental: .natural), octave: 2), + Pitch(key: Key(type: .b, accidental: .flat), octave: 2), + Pitch(key: Key(type: .e, accidental: .flat), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4) ] case .dropA: return [ - Note(type: .a, octave: 1), - Note(type: .e, octave: 2), - Note(type: .a, octave: 2), - Note(type: .d, octave: 3), - Note(type: .gFlat, octave: 3), - Note(type: .b, octave: 3) + Pitch(key: Key(type: .a, accidental: .natural), octave: 1), + Pitch(key: Key(type: .e, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .flat), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3) ] case .openD: return [ - Note(type: .d, octave: 2), - Note(type: .a, octave: 2), - Note(type: .d, octave: 3), - Note(type: .gFlat, octave: 3), - Note(type: .a, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .flat), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .openDMinor: return [ - Note(type: .d, octave: 2), - Note(type: .a, octave: 2), - Note(type: .d, octave: 3), - Note(type: .f, octave: 3), - Note(type: .a, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .f, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .openG: return [ - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .b, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .openGMinor: return [ - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .bFlat, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .flat), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .openC: return [ - Note(type: .c, octave: 2), - Note(type: .g, octave: 2), - Note(type: .c, octave: 3), - Note(type: .g, octave: 3), - Note(type: .c, octave: 4), - Note(type: .e, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4) ] case .openDFlat: return [ - Note(type: .dFlat, octave: 2), - Note(type: .gFlat, octave: 2), - Note(type: .b, octave: 3), - Note(type: .e, octave: 3), - Note(type: .aFlat, octave: 3), - Note(type: .dFlat, octave: 4) + Pitch(key: Key(type: .d, accidental: .flat), octave: 2), + Pitch(key: Key(type: .g, accidental: .flat), octave: 2), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .flat), octave: 3), + Pitch(key: Key(type: .d, accidental: .flat), octave: 4) ] case .openCMinor: return [ - Note(type: .c, octave: 2), - Note(type: .g, octave: 2), - Note(type: .c, octave: 3), - Note(type: .g, octave: 3), - Note(type: .c, octave: 4), - Note(type: .eFlat, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .e, accidental: .flat), octave: 4) ] case .openE7: return [ - Note(type: .e, octave: 2), - Note(type: .aFlat, octave: 2), - Note(type: .d, octave: 3), - Note(type: .e, octave: 3), - Note(type: .b, octave: 3), - Note(type: .e, octave: 4) + Pitch(key: Key(type: .e, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .flat), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4) ] case .openEMinor7: return [ - Note(type: .e, octave: 2), - Note(type: .b, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .b, octave: 3), - Note(type: .e, octave: 4) + Pitch(key: Key(type: .e, accidental: .natural), octave: 2), + Pitch(key: Key(type: .b, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4) ] case .openGMajor7: return [ - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .gFlat, octave: 3), - Note(type: .b, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .flat), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .openAMinor: return [ - Note(type: .e, octave: 2), - Note(type: .a, octave: 2), - Note(type: .e, octave: 3), - Note(type: .a, octave: 3), - Note(type: .c, octave: 4), - Note(type: .e, octave: 4) + Pitch(key: Key(type: .e, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4) ] case .openAMinor7: return [ - Note(type: .e, octave: 2), - Note(type: .a, octave: 2), - Note(type: .e, octave: 3), - Note(type: .g, octave: 3), - Note(type: .c, octave: 4), - Note(type: .e, octave: 4) + Pitch(key: Key(type: .e, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4) ] case .openE: return [ - Note(type: .e, octave: 2), - Note(type: .b, octave: 2), - Note(type: .e, octave: 3), - Note(type: .aFlat, octave: 3), - Note(type: .b, octave: 3), - Note(type: .e, octave: 4) + Pitch(key: Key(type: .e, accidental: .natural), octave: 2), + Pitch(key: Key(type: .b, accidental: .natural), octave: 2), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .flat), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4) ] case .openA: return [ - Note(type: .e, octave: 2), - Note(type: .a, octave: 2), - Note(type: .dFlat, octave: 3), - Note(type: .e, octave: 3), - Note(type: .a, octave: 3), - Note(type: .e, octave: 4) + Pitch(key: Key(type: .e, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .flat), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4) ] case .c: return [ - Note(type: .c, octave: 2), - Note(type: .f, octave: 2), - Note(type: .bFlat, octave: 2), - Note(type: .eFlat, octave: 3), - Note(type: .g, octave: 3), - Note(type: .c, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .f, accidental: .natural), octave: 2), + Pitch(key: Key(type: .b, accidental: .flat), octave: 2), + Pitch(key: Key(type: .e, accidental: .flat), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4) ] case .dFlat: return [ - Note(type: .dFlat, octave: 2), - Note(type: .gFlat, octave: 2), - Note(type: .b, octave: 2), - Note(type: .e, octave: 3), - Note(type: .aFlat, octave: 3), - Note(type: .dFlat, octave: 4) + Pitch(key: Key(type: .d, accidental: .flat), octave: 2), + Pitch(key: Key(type: .g, accidental: .flat), octave: 2), + Pitch(key: Key(type: .b, accidental: .natural), octave: 2), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .flat), octave: 3), + Pitch(key: Key(type: .d, accidental: .flat), octave: 4) ] case .bFlat: return [ - Note(type: .bFlat, octave: 1), - Note(type: .eFlat, octave: 2), - Note(type: .aFlat, octave: 2), - Note(type: .dFlat, octave: 3), - Note(type: .f, octave: 3), - Note(type: .bFlat, octave: 3) + Pitch(key: Key(type: .b, accidental: .flat), octave: 1), + Pitch(key: Key(type: .e, accidental: .flat), octave: 2), + Pitch(key: Key(type: .a, accidental: .flat), octave: 2), + Pitch(key: Key(type: .d, accidental: .flat), octave: 3), + Pitch(key: Key(type: .f, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .flat), octave: 3) ] case .baritone: return [ - Note(type: .a, octave: 1), - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), - Note(type: .c, octave: 3), - Note(type: .e, octave: 3), - Note(type: .a, octave: 3) + Pitch(key: Key(type: .a, accidental: .natural), octave: 1), + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3) ] case .dadddd: return [ - Note(type: .d, octave: 2), - Note(type: .a, octave: 2), - Note(type: .d, octave: 3), - Note(type: .d, octave: 3), - Note(type: .d, octave: 4), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .cgdgbd: return [ - Note(type: .c, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .b, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .cgdgbe: return [ - Note(type: .c, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .b, octave: 3), - Note(type: .e, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4) ] case .dadead: return [ - Note(type: .d, octave: 2), - Note(type: .a, octave: 2), - Note(type: .d, octave: 3), - Note(type: .e, octave: 3), - Note(type: .a, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .dgdgad: return [ - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .a, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .openDSus2: return [ - Note(type: .d, octave: 2), - Note(type: .a, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .a, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .openGSus2: return [ - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .c, octave: 4), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .g6: return [ - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .b, octave: 3), - Note(type: .e, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4) ] case .modalG: return [ - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .c, octave: 4), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .overtone: return [ - Note(type: .c, octave: 3), - Note(type: .e, octave: 3), - Note(type: .g, octave: 3), - Note(type: .bFlat, octave: 3), - Note(type: .c, octave: 4), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .flat), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .pentatonic: return [ - Note(type: .a, octave: 2), - Note(type: .c, octave: 3), - Note(type: .d, octave: 3), - Note(type: .e, octave: 3), - Note(type: .g, octave: 3), - Note(type: .a, octave: 4) + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 4) ] case .minorThriad: return [ - Note(type: .c, octave: 3), - Note(type: .eFlat, octave: 3), - Note(type: .gFlat, octave: 3), - Note(type: .a, octave: 3), - Note(type: .c, octave: 4), - Note(type: .eFlat, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .flat), octave: 3), + Pitch(key: Key(type: .g, accidental: .flat), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .e, accidental: .flat), octave: 4) ] case .majorThriad: return [ - Note(type: .c, octave: 3), - Note(type: .e, octave: 3), - Note(type: .aFlat, octave: 3), - Note(type: .c, octave: 4), - Note(type: .e, octave: 4), - Note(type: .aFlat, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .flat), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4), + Pitch(key: Key(type: .a, accidental: .flat), octave: 4) ] case .allFourths: return [ - Note(type: .e, octave: 2), - Note(type: .a, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .c, octave: 4), - Note(type: .f, octave: 4) + Pitch(key: Key(type: .e, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .f, accidental: .natural), octave: 4) ] case .agumentedFourths: return [ - Note(type: .c, octave: 2), - Note(type: .gFlat, octave: 2), - Note(type: .c, octave: 3), - Note(type: .gFlat, octave: 3), - Note(type: .c, octave: 4), - Note(type: .gFlat, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .flat), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .flat), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .g, accidental: .flat), octave: 4) ] case .slowMotion: return [ - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .f, octave: 3), - Note(type: .c, octave: 4), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .f, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .admiral: return [ - Note(type: .c, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .b, octave: 3), - Note(type: .c, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4) ] case .buzzard: return [ - Note(type: .c, octave: 2), - Note(type: .f, octave: 2), - Note(type: .c, octave: 3), - Note(type: .g, octave: 3), - Note(type: .bFlat, octave: 3), - Note(type: .f, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .f, accidental: .natural), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .flat), octave: 3), + Pitch(key: Key(type: .f, accidental: .natural), octave: 4) ] case .face: return [ - Note(type: .c, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .a, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .fourAndTwenty: return [ - Note(type: .d, octave: 2), - Note(type: .a, octave: 2), - Note(type: .d, octave: 3), - Note(type: .d, octave: 3), - Note(type: .a, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .ostrich: return [ - Note(type: .d, octave: 2), - Note(type: .d, octave: 3), - Note(type: .d, octave: 3), - Note(type: .d, octave: 3), - Note(type: .d, octave: 4), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .capo200: return [ - Note(type: .c, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .eFlat, octave: 3), - Note(type: .d, octave: 4), - Note(type: .eFlat, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .flat), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4), + Pitch(key: Key(type: .e, accidental: .flat), octave: 4) ] case .balalaika: return [ - Note(type: .e, octave: 2), - Note(type: .a, octave: 2), - Note(type: .d, octave: 3), - Note(type: .e, octave: 3), - Note(type: .e, octave: 3), - Note(type: .a, octave: 3) + Pitch(key: Key(type: .e, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3) ] case .charango: return [ - Note(type: .g, octave: 2), - Note(type: .c, octave: 3), - Note(type: .e, octave: 3), - Note(type: .a, octave: 3), - Note(type: .e, octave: 4) + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4) ] case .citternOne: return [ - Note(type: .c, octave: 2), - Note(type: .f, octave: 2), - Note(type: .c, octave: 3), - Note(type: .g, octave: 3), - Note(type: .c, octave: 4), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .f, accidental: .natural), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .citternTwo: return [ - Note(type: .c, octave: 2), - Note(type: .g, octave: 2), - Note(type: .c, octave: 3), - Note(type: .g, octave: 3), - Note(type: .c, octave: 4), - Note(type: .g, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .g, accidental: .natural), octave: 4) ] case .dobro: return [ - Note(type: .g, octave: 2), - Note(type: .b, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .b, octave: 3), - Note(type: .d, octave: 4) + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .b, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4) ] case .leftty: return [ - Note(type: .e, octave: 4), - Note(type: .b, octave: 3), - Note(type: .g, octave: 3), - Note(type: .d, octave: 3), - Note(type: .a, octave: 2), - Note(type: .e, octave: 2) + Pitch(key: Key(type: .e, accidental: .natural), octave: 4), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .e, accidental: .natural), octave: 2) ] case .mandoguitar: return [ - Note(type: .c, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .a, octave: 3), - Note(type: .e, octave: 4), - Note(type: .b, octave: 4) + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .a, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4), + Pitch(key: Key(type: .b, accidental: .natural), octave: 4) ] case .rustyCage: return [ - Note(type: .b, octave: 1), - Note(type: .a, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .b, octave: 3), - Note(type: .e, octave: 4) + Pitch(key: Key(type: .b, accidental: .natural), octave: 1), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4) ] } } @@ -835,175 +835,175 @@ public enum BassTuning: FretboardTuning { case fbeadgc7String case standard8String - public var strings: [Note] { + public var strings: [Pitch] { switch self { case .standard4String: return [ - Note(type: .e, octave: 1), - Note(type: .a, octave: 1), - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), + Pitch(key: Key(type: .e, accidental: .natural), octave: 1), + Pitch(key: Key(type: .a, accidental: .natural), octave: 1), + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), ] case .standard5String: return [ - Note(type: .b, octave: 0), - Note(type: .e, octave: 1), - Note(type: .a, octave: 1), - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), + Pitch(key: Key(type: .b, accidental: .natural), octave: 0), + Pitch(key: Key(type: .e, accidental: .natural), octave: 1), + Pitch(key: Key(type: .a, accidental: .natural), octave: 1), + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), ] case .standard6String: return [ - Note(type: .b, octave: 0), - Note(type: .e, octave: 1), - Note(type: .a, octave: 1), - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), - Note(type: .c, octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 0), + Pitch(key: Key(type: .e, accidental: .natural), octave: 1), + Pitch(key: Key(type: .a, accidental: .natural), octave: 1), + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), ] case .dropD4String: return [ - Note(type: .d, octave: 1), - Note(type: .a, octave: 1), - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 1), + Pitch(key: Key(type: .a, accidental: .natural), octave: 1), + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), ] case .dropB4String: return [ - Note(type: .d, octave: 1), - Note(type: .a, octave: 1), - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 1), + Pitch(key: Key(type: .a, accidental: .natural), octave: 1), + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), ] case .openA4String: return [ - Note(type: .e, octave: 1), - Note(type: .a, octave: 1), - Note(type: .e, octave: 2), - Note(type: .a, octave: 2), + Pitch(key: Key(type: .e, accidental: .natural), octave: 1), + Pitch(key: Key(type: .a, accidental: .natural), octave: 1), + Pitch(key: Key(type: .e, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), ] case .openE4String: return [ - Note(type: .e, octave: 1), - Note(type: .b, octave: 1), - Note(type: .e, octave: 2), - Note(type: .aFlat, octave: 2), + Pitch(key: Key(type: .e, accidental: .natural), octave: 1), + Pitch(key: Key(type: .b, accidental: .natural), octave: 1), + Pitch(key: Key(type: .e, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .flat), octave: 2), ] case .e7sus44string: return [ - Note(type: .b, octave: 1), - Note(type: .e, octave: 1), - Note(type: .a, octave: 2), - Note(type: .d, octave: 2), + Pitch(key: Key(type: .b, accidental: .natural), octave: 1), + Pitch(key: Key(type: .e, accidental: .natural), octave: 1), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), ] case .gsus44String: return [ - Note(type: .d, octave: 1), - Note(type: .a, octave: 1), - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 1), + Pitch(key: Key(type: .a, accidental: .natural), octave: 1), + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), ] case .tenor4String: return [ - Note(type: .a, octave: 1), - Note(type: .d, octave: 1), - Note(type: .g, octave: 2), - Note(type: .c, octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 1), + Pitch(key: Key(type: .d, accidental: .natural), octave: 1), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), ] case .piccolo4String: return [ - Note(type: .e, octave: 2), - Note(type: .a, octave: 2), - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 2), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), ] case .halfStepDown4String: return [ - Note(type: .eFlat, octave: 1), - Note(type: .aFlat, octave: 1), - Note(type: .dFlat, octave: 2), - Note(type: .gFlat, octave: 2), + Pitch(key: Key(type: .e, accidental: .flat), octave: 1), + Pitch(key: Key(type: .a, accidental: .flat), octave: 1), + Pitch(key: Key(type: .d, accidental: .flat), octave: 2), + Pitch(key: Key(type: .g, accidental: .flat), octave: 2), ] case .halfStepDown5String: return[ - Note(type: .bFlat, octave: 0), - Note(type: .eFlat, octave: 1), - Note(type: .aFlat, octave: 1), - Note(type: .dFlat, octave: 2), - Note(type: .gFlat, octave: 2), + Pitch(key: Key(type: .b, accidental: .flat), octave: 0), + Pitch(key: Key(type: .e, accidental: .flat), octave: 1), + Pitch(key: Key(type: .a, accidental: .flat), octave: 1), + Pitch(key: Key(type: .d, accidental: .flat), octave: 2), + Pitch(key: Key(type: .g, accidental: .flat), octave: 2), ] case .halfStepDown6String: return [ - Note(type: .bFlat, octave: 0), - Note(type: .eFlat, octave: 1), - Note(type: .aFlat, octave: 1), - Note(type: .dFlat, octave: 2), - Note(type: .gFlat, octave: 2), - Note(type: .b, octave: 3), + Pitch(key: Key(type: .b, accidental: .flat), octave: 0), + Pitch(key: Key(type: .e, accidental: .flat), octave: 1), + Pitch(key: Key(type: .a, accidental: .flat), octave: 1), + Pitch(key: Key(type: .d, accidental: .flat), octave: 2), + Pitch(key: Key(type: .g, accidental: .flat), octave: 2), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), ] case .fullStepDown4String: return [ - Note(type: .d, octave: 1), - Note(type: .g, octave: 1), - Note(type: .c, octave: 2), - Note(type: .f, octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 1), + Pitch(key: Key(type: .g, accidental: .natural), octave: 1), + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .f, accidental: .natural), octave: 2), ] case .fullStepDown5String: return [ - Note(type: .a, octave: 0), - Note(type: .d, octave: 1), - Note(type: .g, octave: 1), - Note(type: .c, octave: 2), - Note(type: .f, octave: 2) + Pitch(key: Key(type: .a, accidental: .natural), octave: 0), + Pitch(key: Key(type: .d, accidental: .natural), octave: 1), + Pitch(key: Key(type: .g, accidental: .natural), octave: 1), + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .f, accidental: .natural), octave: 2) ] case .eadgcf6String: return [ - Note(type: .e, octave: 0), - Note(type: .a, octave: 1), - Note(type: .d, octave: 1), - Note(type: .g, octave: 2), - Note(type: .c, octave: 2), - Note(type: .f, octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 0), + Pitch(key: Key(type: .a, accidental: .natural), octave: 1), + Pitch(key: Key(type: .d, accidental: .natural), octave: 1), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 2), + Pitch(key: Key(type: .f, accidental: .natural), octave: 3), ] case .fbeadg6String: return [ - Note(type: .gFlat, octave: 0), - Note(type: .b, octave: 1), - Note(type: .e, octave: 1), - Note(type: .a, octave: 2), - Note(type: .d, octave: 2), - Note(type: .g, octave: 3), + Pitch(key: Key(type: .g, accidental: .flat), octave: 0), + Pitch(key: Key(type: .b, accidental: .natural), octave: 1), + Pitch(key: Key(type: .e, accidental: .natural), octave: 1), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), ] case .standard7String: return [ - Note(type: .b, octave: 0), - Note(type: .e, octave: 1), - Note(type: .a, octave: 1), - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), - Note(type: .d, octave: 3), - Note(type: .c, octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 0), + Pitch(key: Key(type: .e, accidental: .natural), octave: 1), + Pitch(key: Key(type: .a, accidental: .natural), octave: 1), + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), ] case .fbeadgc7String: return [ - Note(type: .gFlat, octave: 0), - Note(type: .b, octave: 1), - Note(type: .e, octave: 1), - Note(type: .a, octave: 2), - Note(type: .d, octave: 2), - Note(type: .g, octave: 3), - Note(type: .c, octave: 3), + Pitch(key: Key(type: .g, accidental: .flat), octave: 0), + Pitch(key: Key(type: .b, accidental: .natural), octave: 1), + Pitch(key: Key(type: .e, accidental: .natural), octave: 1), + Pitch(key: Key(type: .a, accidental: .natural), octave: 2), + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), ] case .standard8String: return [ - Note(type: .gFlat, octave: 0), - Note(type: .b, octave: 0), - Note(type: .e, octave: 1), - Note(type: .a, octave: 1), - Note(type: .d, octave: 2), - Note(type: .g, octave: 2), - Note(type: .c, octave: 3), - Note(type: .f, octave: 3), + Pitch(key: Key(type: .g, accidental: .flat), octave: 0), + Pitch(key: Key(type: .b, accidental: .natural), octave: 0), + Pitch(key: Key(type: .e, accidental: .natural), octave: 1), + Pitch(key: Key(type: .a, accidental: .natural), octave: 1), + Pitch(key: Key(type: .d, accidental: .natural), octave: 2), + Pitch(key: Key(type: .g, accidental: .natural), octave: 2), + Pitch(key: Key(type: .c, accidental: .natural), octave: 3), + Pitch(key: Key(type: .f, accidental: .natural), octave: 3), ] } } @@ -1079,7 +1079,7 @@ extension BassTuning { .eadgcf6String, .fbeadg6String, .fbeadgc7String, - ] + ] } // MARK: UkeleleTuning @@ -1091,35 +1091,35 @@ public enum UkeleleTuning: FretboardTuning { case baritone case tenor - public var strings: [Note] { + public var strings: [Pitch] { switch self { case .standard: return [ - Note(type: .g, octave: 4), - Note(type: .c, octave: 4), - Note(type: .e, octave: 4), - Note(type: .a, octave: 4) + Pitch(key: Key(type: .g, accidental: .natural), octave: 4), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4), + Pitch(key: Key(type: .a, accidental: .natural), octave: 4) ] case .soprano: return [ - Note(type: .a, octave: 4), - Note(type: .d, octave: 4), - Note(type: .gFlat, octave: 4), - Note(type: .b, octave: 4) + Pitch(key: Key(type: .a, accidental: .natural), octave: 4), + Pitch(key: Key(type: .d, accidental: .natural), octave: 4), + Pitch(key: Key(type: .g, accidental: .flat), octave: 4), + Pitch(key: Key(type: .b, accidental: .natural), octave: 4) ] case .baritone: return [ - Note(type: .d, octave: 3), - Note(type: .g, octave: 3), - Note(type: .b, octave: 3), - Note(type: .e, octave: 4) + Pitch(key: Key(type: .d, accidental: .natural), octave: 3), + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .b, accidental: .natural), octave: 3), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4) ] case .tenor: return [ - Note(type: .g, octave: 3), - Note(type: .c, octave: 4), - Note(type: .e, octave: 4), - Note(type: .a, octave: 4) + Pitch(key: Key(type: .g, accidental: .natural), octave: 3), + Pitch(key: Key(type: .c, accidental: .natural), octave: 4), + Pitch(key: Key(type: .e, accidental: .natural), octave: 4), + Pitch(key: Key(type: .a, accidental: .natural), octave: 4) ] } } @@ -1151,10 +1151,10 @@ extension UkeleleTuning { /// Creates custom tuning with any number of string instrument. public struct CustomTuning: FretboardTuning { - public var strings: [Note] + public var strings: [Pitch] public var description: String - public init(strings: [Note], description: String) { + public init(strings: [Pitch], description: String) { self.strings = strings self.description = description } diff --git a/Source/FretboardView.swift b/Source/FretboardView.swift index 5c934b1..dab7119 100644 --- a/Source/FretboardView.swift +++ b/Source/FretboardView.swift @@ -25,7 +25,7 @@ public class FretLabel: FRView { #if os(iOS) || os(tvOS) public override init(frame: CGRect) { super.init(frame: frame) - textLayer.alignmentMode = kCAAlignmentCenter + textLayer.alignmentMode = CATextLayerAlignmentMode.center textLayer.contentsScale = UIScreen.main.scale layer.addSublayer(textLayer) } @@ -33,8 +33,8 @@ public class FretLabel: FRView { public override init(frame frameRect: NSRect) { super.init(frame: frameRect) wantsLayer = true - textLayer.alignmentMode = kCAAlignmentCenter - textLayer.contentsScale = NSScreen.main()?.backingScaleFactor ?? 1 + textLayer.alignmentMode = CATextLayerAlignmentMode.center + textLayer.contentsScale = NSScreen.main?.backingScaleFactor ?? 1 layer?.addSublayer(textLayer) } #endif @@ -117,7 +117,7 @@ public class FretView: FRView { } required public init?(coder: NSCoder) { - note = FretboardNote(note: Note(midiNote: 0), fretIndex: 0, stringIndex: 0) + note = FretboardNote(note: Pitch(midiNote: 0), fretIndex: 0, stringIndex: 0) super.init(coder: coder) setup() } @@ -151,7 +151,7 @@ public class FretView: FRView { #if os(iOS) || os(tvOS) textLayer.contentsScale = UIScreen.main.scale #elseif os(OSX) - textLayer.contentsScale = NSScreen.main()?.backingScaleFactor ?? 1 + textLayer.contentsScale = NSScreen.main?.backingScaleFactor ?? 1 #endif } @@ -370,13 +370,13 @@ public class FretView: FRView { // TextLayer let noteText = NSAttributedString( - string: "\(note.note.type)", + string: "\(note.note.key)", attributes: [ - NSForegroundColorAttributeName: textColor, - NSFontAttributeName: FRFont.systemFont(ofSize: noteSize / 2) + NSAttributedString.Key.foregroundColor: textColor, + NSAttributedString.Key.font: FRFont.systemFont(ofSize: noteSize / 2) ]) - textLayer.alignmentMode = kCAAlignmentCenter + textLayer.alignmentMode = CATextLayerAlignmentMode.center textLayer.string = isDrawSelectedNoteText && note.isSelected ? noteText : nil textLayer.frame = layer.bounds } @@ -549,10 +549,10 @@ public class FretboardView: FRView, FretboardDelegate { } label.textLayer.string = NSAttributedString( - string: "\(fretboard.strings[index].type)", + string: "\(fretboard.strings[index].key)", attributes: [ - NSForegroundColorAttributeName: stringLabelColor, - NSFontAttributeName: FRFont.systemFont(ofSize: (min(stringLabelSize.width, stringLabelSize.height) * 2) / 3) + NSAttributedString.Key.foregroundColor: stringLabelColor, + NSAttributedString.Key.font: FRFont.systemFont(ofSize: (min(stringLabelSize.width, stringLabelSize.height) * 2) / 3) ]) label.frame = CGRect(origin: position, size: stringLabelSize) } @@ -580,8 +580,8 @@ public class FretboardView: FRView, FretboardDelegate { label.textLayer.string = NSAttributedString( string: "\(fretboard.startIndex + index)", attributes: [ - NSForegroundColorAttributeName: fretLabelColor, - NSFontAttributeName: FRFont.systemFont(ofSize: (min(fretLabelSize.width, fretLabelSize.height) * 2) / 3) + NSAttributedString.Key.foregroundColor: fretLabelColor, + NSAttributedString.Key.font: FRFont.systemFont(ofSize: (min(fretLabelSize.width, fretLabelSize.height) * 2) / 3) ]) } label.frame = CGRect(origin: position, size: fretLabelSize)