├── .gitignore ├── img ├── window.png └── quicklook.png ├── qlMIDI ├── .DS_Store ├── Media.xcassets │ ├── .DS_Store │ ├── Contents.json │ ├── Pause.imageset │ │ ├── Pause@1x.png │ │ ├── Pause@2x.png │ │ └── Contents.json │ ├── Play.imageset │ │ ├── Play@1x.png │ │ ├── Play@2x.png │ │ └── Contents.json │ ├── previewIcon.imageset │ │ ├── mac256pt1x.png │ │ ├── mac512pt1x.png │ │ ├── mac512pt2x.png │ │ └── Contents.json │ └── BacktoPreview.imageset │ │ ├── BacktoPreview@3x-1.png │ │ └── Contents.json ├── qlMIDI.entitlements ├── Info.plist ├── PreviewProvider.swift ├── PreviewViewController.swift └── Base.lproj │ └── PreviewViewController.xib ├── APPlayMIDI ├── Assets.xcassets │ ├── Contents.json │ ├── .DS_Store │ ├── Pause.imageset │ │ ├── Pause@1x.png │ │ ├── Pause@2x.png │ │ └── Contents.json │ ├── Play.imageset │ │ ├── Play@1x.png │ │ ├── Play@2x.png │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── APPlayMIDI-128.png │ │ ├── APPlayMIDI-16.png │ │ ├── APPlayMIDI-256.png │ │ ├── APPlayMIDI-257.png │ │ ├── APPlayMIDI-32.png │ │ ├── APPlayMIDI-33.png │ │ ├── APPlayMIDI-512.png │ │ ├── APPlayMIDI-513.png │ │ ├── APPlayMIDI-64.png │ │ ├── APPlayMIDI-1024.png │ │ └── Contents.json │ └── BacktoPreview.imageset │ │ ├── BacktoPreview@3x-1.png │ │ └── Contents.json ├── APPlayMIDI.entitlements ├── WindowController.swift ├── AppDelegate.swift ├── Document.swift ├── Info.plist ├── ViewController.swift └── Base.lproj │ └── Main.storyboard ├── APPlayMIDI.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcuserdata │ │ └── Ben.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcuserdata │ └── Ben.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── xcshareddata │ └── xcschemes │ │ ├── APPlayMIDI.xcscheme │ │ └── qlMIDI.xcscheme └── project.pbxproj ├── LICENCE.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | qlMIDI/.DS_Store 3 | APPlayMIDI/.DS_Store 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /img/window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/img/window.png -------------------------------------------------------------------------------- /qlMIDI/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/qlMIDI/.DS_Store -------------------------------------------------------------------------------- /img/quicklook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/img/quicklook.png -------------------------------------------------------------------------------- /qlMIDI/Media.xcassets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/qlMIDI/Media.xcassets/.DS_Store -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /qlMIDI/Media.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/.DS_Store -------------------------------------------------------------------------------- /qlMIDI/Media.xcassets/Pause.imageset/Pause@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/qlMIDI/Media.xcassets/Pause.imageset/Pause@1x.png -------------------------------------------------------------------------------- /qlMIDI/Media.xcassets/Pause.imageset/Pause@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/qlMIDI/Media.xcassets/Pause.imageset/Pause@2x.png -------------------------------------------------------------------------------- /qlMIDI/Media.xcassets/Play.imageset/Play@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/qlMIDI/Media.xcassets/Play.imageset/Play@1x.png -------------------------------------------------------------------------------- /qlMIDI/Media.xcassets/Play.imageset/Play@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/qlMIDI/Media.xcassets/Play.imageset/Play@2x.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/Pause.imageset/Pause@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/Pause.imageset/Pause@1x.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/Pause.imageset/Pause@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/Pause.imageset/Pause@2x.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/Play.imageset/Play@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/Play.imageset/Play@1x.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/Play.imageset/Play@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/Play.imageset/Play@2x.png -------------------------------------------------------------------------------- /qlMIDI/Media.xcassets/previewIcon.imageset/mac256pt1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/qlMIDI/Media.xcassets/previewIcon.imageset/mac256pt1x.png -------------------------------------------------------------------------------- /qlMIDI/Media.xcassets/previewIcon.imageset/mac512pt1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/qlMIDI/Media.xcassets/previewIcon.imageset/mac512pt1x.png -------------------------------------------------------------------------------- /qlMIDI/Media.xcassets/previewIcon.imageset/mac512pt2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/qlMIDI/Media.xcassets/previewIcon.imageset/mac512pt2x.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-128.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-16.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-256.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-257.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-257.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-32.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-33.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-512.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-513.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-513.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-64.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/AppIcon.appiconset/APPlayMIDI-1024.png -------------------------------------------------------------------------------- /qlMIDI/Media.xcassets/BacktoPreview.imageset/BacktoPreview@3x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/qlMIDI/Media.xcassets/BacktoPreview.imageset/BacktoPreview@3x-1.png -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/BacktoPreview.imageset/BacktoPreview@3x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI/Assets.xcassets/BacktoPreview.imageset/BacktoPreview@3x-1.png -------------------------------------------------------------------------------- /APPlayMIDI.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /APPlayMIDI.xcodeproj/xcuserdata/Ben.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /APPlayMIDI.xcodeproj/project.xcworkspace/xcuserdata/Ben.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benwiggy/APPlayMIDI/HEAD/APPlayMIDI.xcodeproj/project.xcworkspace/xcuserdata/Ben.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /APPlayMIDI/APPlayMIDI.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.files.user-selected.read-only 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /APPlayMIDI.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/BacktoPreview.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "BacktoPreview@3x-1.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /qlMIDI/Media.xcassets/BacktoPreview.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "BacktoPreview@3x-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /qlMIDI/Media.xcassets/Pause.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Pause@1x.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "Pause@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /qlMIDI/Media.xcassets/Play.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Play@1x.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "Play@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/Pause.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Pause@1x.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "Pause@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/Play.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Play@1x.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "Play@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /qlMIDI/Media.xcassets/previewIcon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mac256pt1x.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "mac512pt1x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "mac512pt2x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /qlMIDI/qlMIDI.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.assets.movies.read-only 8 | 9 | com.apple.security.assets.music.read-only 10 | 11 | com.apple.security.assets.pictures.read-only 12 | 13 | com.apple.security.files.downloads.read-only 14 | 15 | com.apple.security.files.user-selected.read-only 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /APPlayMIDI/WindowController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WindowController.swift 3 | // APPlayMIDI 4 | // 5 | // Created by Ben Byram-Wigfield on 22/10/2019. 6 | // Copyright © 2019 Ben. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class WindowController: NSWindowController { 12 | 13 | required init?(coder: NSCoder) { 14 | super.init(coder: coder) 15 | shouldCascadeWindows = true 16 | } 17 | 18 | override func windowDidLoad() { 19 | super.windowDidLoad() 20 | 21 | // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /APPlayMIDI/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // APPlayMIDI 4 | // 5 | // Created by Ben on 20/08/2019. 6 | // Copyright © 2019 Ben. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | @NSApplicationMain 12 | class AppDelegate: NSObject, NSApplicationDelegate { 13 | 14 | func applicationShouldOpenUntitledFile(_ sender: NSApplication) -> Bool { 15 | return false 16 | } 17 | 18 | func applicationDidFinishLaunching(_ aNotification: Notification) { 19 | // Insert code here to initialize your application 20 | } 21 | 22 | func applicationWillTerminate(_ aNotification: Notification) { 23 | // Insert code here to tear down your application 24 | } 25 | 26 | 27 | } 28 | 29 | -------------------------------------------------------------------------------- /qlMIDI/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionAttributes 8 | 9 | QLIsDataBasedPreview 10 | 11 | QLSupportedContentTypes 12 | 13 | public.midi-audio 14 | 15 | QLSupportsSearchableItems 16 | 17 | 18 | NSExtensionMainNibFile 19 | PreviewViewController 20 | NSExtensionPointIdentifier 21 | com.apple.quicklook.preview 22 | NSExtensionPrincipalClass 23 | $(PRODUCT_MODULE_NAME).PreviewViewController 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /APPlayMIDI.xcodeproj/xcuserdata/Ben.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | APPlayMIDI.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | qlMIDI.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 1 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | B5051864230C2C9E0024884E 21 | 22 | primary 23 | 24 | 25 | B53CD76D28738D46002A1C80 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /LICENCE.txt: -------------------------------------------------------------------------------- 1 | The binary and source code of APPlayMIDI.app are made available under the terms of the MIT Licence: 2 | 3 | © 2019 Ben Byram-Wigfield 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /APPlayMIDI/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "APPlayMIDI-16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "APPlayMIDI-33.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "APPlayMIDI-32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "APPlayMIDI-64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "APPlayMIDI-128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "APPlayMIDI-257.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "APPlayMIDI-256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "APPlayMIDI-513.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "APPlayMIDI-512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "APPlayMIDI-1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /APPlayMIDI/Document.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Document.swift 3 | // APPlayMIDI 4 | // 5 | // Created by Ben on 20/08/2019. 6 | // Copyright © 2019 Ben. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import AVFoundation 11 | import AppKit 12 | 13 | // Create a PasteboardType for MIDI data 14 | extension NSPasteboard.PasteboardType { 15 | static let typeMidi = NSPasteboard.PasteboardType(rawValue: "public.midi-audio") 16 | } 17 | 18 | class Document: NSDocument { 19 | var theMIDIPlayer: AVMIDIPlayer? 20 | var myData: Data? 21 | 22 | override init() { 23 | super.init() 24 | } 25 | 26 | override class var autosavesInPlace: Bool { 27 | return false 28 | } 29 | 30 | override func makeWindowControllers() { 31 | // Returns the Storyboard that contains your Document window. 32 | let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil) 33 | let windowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("Document Window Controller")) as! NSWindowController 34 | self.addWindowController(windowController) 35 | windowController.shouldCascadeWindows = true 36 | } 37 | 38 | @IBAction func copy(_: Any) { 39 | let pboard = NSPasteboard.general 40 | pboard.clearContents() 41 | pboard.setData(myData, forType: .typeMidi) 42 | } 43 | 44 | // override func data(ofType typeName: String) throws -> Data { 45 | // throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil) 46 | // } 47 | 48 | override func read(from data: Data, ofType typeName: String) throws { 49 | self.theMIDIPlayer = try AVMIDIPlayer.init(data: data, soundBankURL: nil) 50 | self.myData = data 51 | if self.theMIDIPlayer == nil { 52 | throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil) 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /qlMIDI/PreviewProvider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PreviewProvider.swift 3 | // qlMIDI 4 | // 5 | // Created by Ben on 04/07/2022. 6 | // Copyright © 2022 Ben. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import Quartz 11 | 12 | class PreviewProvider: QLPreviewProvider, QLPreviewingController { 13 | 14 | 15 | /* 16 | Use a QLPreviewProvider to provide data-based previews. 17 | 18 | To set up your extension as a data-based preview extension: 19 | 20 | - Modify the extension's Info.plist by setting 21 | QLIsDataBasedPreview 22 | 23 | 24 | - Add the supported content types to QLSupportedContentTypes array in the extension's Info.plist. 25 | 26 | - Change the NSExtensionPrincipalClass to this class. 27 | e.g. 28 | NSExtensionPrincipalClass 29 | $(PRODUCT_MODULE_NAME).PreviewProvider 30 | 31 | - Implement providePreview(for:) 32 | */ 33 | 34 | func providePreview(for request: QLFilePreviewRequest) async throws -> QLPreviewReply { 35 | 36 | //You can create a QLPreviewReply in several ways, depending on the format of the data you want to return. 37 | //To return Data of a supported content type: 38 | 39 | let contentType = UTType.plainText // replace with your data type 40 | 41 | let reply = QLPreviewReply.init(dataOfContentType: contentType, contentSize: CGSize.init(width: 800, height: 400)) { (replyToUpdate : QLPreviewReply) in 42 | 43 | let data = Data("Hello world".utf8) 44 | 45 | //setting the stringEncoding for text and html data is optional and defaults to String.Encoding.utf8 46 | replyToUpdate.stringEncoding = .utf8 47 | 48 | //initialize your data here 49 | 50 | return data 51 | } 52 | 53 | return reply 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /APPlayMIDI/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDocumentTypes 8 | 9 | 10 | CFBundleTypeExtensions 11 | 12 | [midi] 13 | 14 | CFBundleTypeIconFile 15 | 16 | CFBundleTypeName 17 | MIDI audio 18 | CFBundleTypeOSTypes 19 | 20 | ???? 21 | 22 | CFBundleTypeRole 23 | Viewer 24 | LSItemContentTypes 25 | 26 | public.midi-audio 27 | 28 | NSDocumentClass 29 | $(PRODUCT_MODULE_NAME).Document 30 | 31 | 32 | CFBundleExecutable 33 | $(EXECUTABLE_NAME) 34 | CFBundleIconFile 35 | 36 | CFBundleIdentifier 37 | $(PRODUCT_BUNDLE_IDENTIFIER) 38 | CFBundleInfoDictionaryVersion 39 | 6.0 40 | CFBundleName 41 | $(PRODUCT_NAME) 42 | CFBundlePackageType 43 | APPL 44 | CFBundleShortVersionString 45 | $(MARKETING_VERSION) 46 | CFBundleVersion 47 | $(CURRENT_PROJECT_VERSION) 48 | LSApplicationCategoryType 49 | public.app-category.music 50 | LSMinimumSystemVersion 51 | $(MACOSX_DEPLOYMENT_TARGET) 52 | NSHumanReadableCopyright 53 | Copyright © 2019 Ben. All rights reserved. 54 | NSMainStoryboardFile 55 | Main 56 | NSPrincipalClass 57 | NSApplication 58 | UTExportedTypeDeclarations 59 | 60 | 61 | UTTypeDescription 62 | MIDI audio 63 | UTTypeIdentifier 64 | public.midi-audio 65 | UTTypeTagSpecification 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /APPlayMIDI.xcodeproj/xcshareddata/xcschemes/APPlayMIDI.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 44 | 46 | 52 | 53 | 54 | 55 | 61 | 63 | 69 | 70 | 71 | 72 | 74 | 75 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # APPlayMIDI 2 | _A simple MIDI file player for MacOS._ 3 | 4 | Ever since 2009, when Apple deprecated the 32-bit QuickTime framework in favour of the newer AVKit, the Mac's flagship media player, QuickTime Player X has refused to play MIDI files. (Despite MIDI file types being associated with the app!) 5 | 6 | The AVKit framework contains a perfectly good player for MIDI files: AVMIDIPlayer, so there's no excuse for not having an app that plays MIDI files. Here's my lightweight implementation. 7 | 8 | ![alt text](img/window.png) 9 | 10 | Each document window contains a slider that both indicates and sets the current play position, and a 'rewind' button to return to the start of the track. Numerical counters show the play position and total duration. 11 | 12 | The app contains a few other features: it can Copy the MIDI data from a document to the clipboard, so it can be pasted into apps that support pasting MIDI data. 13 | 14 | Known apps that support MIDI pasteboard include: Finale. (Let me know of others.) 15 | 16 | You can also drag the file icon from the titlebar into any app that supports MIDI dragging: e.g. Cubase, Dorico... 17 | 18 | If you like this app, please consider buying me a drink! 19 | https://paypal.me/agroovem 20 | 21 | ### QUICK LOOK! ### 22 | 23 | APPlayMIDI now contains a Quick Look Extension, enabling MIDI files to be played directly in the Finder. 24 | 25 | ![alt text](img/quicklook.png) 26 | 27 | The Preview panel, or Quick Look pop-up window, will display three objects: Play/pause button, rewind to start, and a progress indicator. Note that you need to press Play to start the preview (to stop files from auto-playing just by being selected in the Finder). 28 | 29 | This feature is still 'a bit beta'; while it works, there are a few interface issues to sort out. 30 | 31 | ### Installation ### 32 | Click on the Releases link above, or here: https://github.com/benwiggy/APPlayMIDI/releases. Download, unzip and move to the /Applications folder. You then need to right click on the app and select "Open". A dialog will come up, telling you that it is from an 'unidentified developer', but there should be an "Open" button. 33 | You may want to make APPlayMIDI the default file for opening MIDI files. Select a MIDI file, then _Get Info_ (File menu or Command I) select "APPlayMIDI", and then click "Change All". 34 | 35 | The source files are included, for anyone who wants to help improve the quality of the code, add functionality, or use them as the basis of a new app. 36 | 37 | ### OS Versions required and supported ### 38 | 39 | v1.10 does need macOS 12, Monterey, for the Quick Look extension to work. 40 | v.1.04 and 05 are Universal Binaries for Intel and Apple Silicon, and so require Big Sur to work. 41 | v1.02 should work on earlier OSes. 42 | 43 | ### Future ### 44 | Some refinement of the Quick Look code, to enable different behaviours for the preview panel and the Quick Look pop-up window, would be nice. 45 | 46 | v.1.14 Added loop feature. 47 | v.1.12 Fixed memory leak and other fixes. 48 | v.1.10 Quick Look support added. 49 | v.1.05 Fixed an issue with a cropped slider in Monterey. 50 | v.1.04 Universal Binary for Intel and ARM Macs. 51 | v.1.02 The app has been code-signed, but apparently that's still not enough to clear MacOS's quarantine. 52 | v.1.01 fixes an issue where document windows did not cascade. 53 | 54 | -------------------------------------------------------------------------------- /APPlayMIDI.xcodeproj/xcshareddata/xcschemes/qlMIDI.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 6 | 9 | 10 | 16 | 22 | 23 | 24 | 30 | 36 | 37 | 38 | 39 | 40 | 45 | 46 | 47 | 48 | 60 | 62 | 68 | 69 | 70 | 71 | 79 | 81 | 87 | 88 | 89 | 90 | 92 | 93 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /APPlayMIDI/ViewController.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import AVFoundation 3 | import AVKit 4 | import QuickLook 5 | 6 | class ViewController: NSViewController { 7 | var document: Document? { 8 | return self.view.window?.windowController?.document as? Document 9 | } 10 | 11 | var viewMIDIPlayer: AVMIDIPlayer? { 12 | return document?.theMIDIPlayer 13 | } 14 | 15 | var myTimer: Timer? 16 | 17 | @IBOutlet var currentTimeField: NSTextField! 18 | @IBOutlet var theSlider: NSSlider! 19 | @IBOutlet var endTimeField: NSTextField! 20 | @IBOutlet weak var playButton: NSButton! 21 | @IBOutlet weak var loopCheckbox: NSButton! // Outlet for the loop checkbox 22 | 23 | override func viewDidLoad() { 24 | super.viewDidLoad() 25 | 26 | currentTimeField.font = NSFont.monospacedDigitSystemFont(ofSize: 13, weight: .regular) 27 | endTimeField.font = NSFont.monospacedDigitSystemFont(ofSize: 13, weight: .regular) 28 | } 29 | 30 | override func viewDidAppear() { 31 | super.viewDidAppear() 32 | guard let midiPlayer = viewMIDIPlayer else { 33 | print("Error: MIDI Player is not available") 34 | return 35 | } 36 | 37 | theSlider.maxValue = midiPlayer.duration 38 | midiPlayer.prepareToPlay() 39 | 40 | let time = midiPlayer.duration 41 | let timeString = formattedTimeString(time) 42 | endTimeField.stringValue = timeString 43 | 44 | myTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateDisplay), userInfo: nil, repeats: true) 45 | } 46 | 47 | @IBAction func playSwitch(_ sender: NSButton) { 48 | guard let midiPlayer = viewMIDIPlayer else { return } 49 | 50 | if midiPlayer.isPlaying { 51 | midiPlayer.stop() 52 | } else { 53 | midiPlayer.play { 54 | self.completed() 55 | } 56 | } 57 | } 58 | 59 | @IBAction func moveSlider(_ sender: Any) { 60 | guard let midiPlayer = viewMIDIPlayer else { return } 61 | 62 | midiPlayer.stop() 63 | midiPlayer.currentPosition = theSlider.doubleValue 64 | updateDisplay() 65 | playButton.state = .on 66 | midiPlayer.prepareToPlay() 67 | midiPlayer.play { 68 | self.completed() 69 | } 70 | } 71 | 72 | @IBAction func backToStart(_ sender: Any) { 73 | guard let midiPlayer = viewMIDIPlayer else { return } 74 | 75 | midiPlayer.stop() 76 | midiPlayer.currentPosition = 0 77 | playButton.state = .on 78 | midiPlayer.prepareToPlay() 79 | midiPlayer.play { 80 | self.completed() 81 | } 82 | } 83 | 84 | func completed() { 85 | if let midiPlayer = viewMIDIPlayer { 86 | if midiPlayer.currentPosition >= (midiPlayer.duration - 1) { 87 | if self.loopCheckbox.state == .on { 88 | midiPlayer.currentPosition = 0 89 | midiPlayer.prepareToPlay() 90 | midiPlayer.play { 91 | self.completed() 92 | } 93 | } else { 94 | self.playButton.state = .off 95 | } 96 | } else { 97 | self.playButton.state = .off 98 | } 99 | } 100 | } 101 | 102 | @objc func updateDisplay() { 103 | guard let midiPlayer = viewMIDIPlayer else { return } 104 | 105 | if midiPlayer.currentPosition <= midiPlayer.duration { 106 | theSlider.doubleValue = midiPlayer.currentPosition 107 | let timeString = formattedTimeString(midiPlayer.currentPosition) 108 | currentTimeField.stringValue = timeString 109 | } 110 | } 111 | 112 | override func viewDidDisappear() { 113 | super.viewDidDisappear() 114 | document?.theMIDIPlayer = nil 115 | myTimer?.invalidate() 116 | } 117 | 118 | override var representedObject: Any? { 119 | didSet { 120 | // Update the view, if already loaded. 121 | } 122 | } 123 | 124 | private func formattedTimeString(_ time: TimeInterval) -> String { 125 | let hours = Int(floor(time / 3600)) 126 | let minutes = Int(floor((time.truncatingRemainder(dividingBy: 3600)) / 60)) 127 | let seconds = Int(time) % 60 128 | return String(format: "%02d:%02d:%02d", hours, minutes, seconds) 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /qlMIDI/PreviewViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PreviewViewController.swift 3 | // qlMIDI 4 | // 5 | // Created by Ben on 04/07/2022. 6 | // Copyright © 2022 Ben. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import Quartz 11 | import AVFoundation 12 | 13 | class PreviewViewController: NSViewController, QLPreviewingController { 14 | 15 | override var nibName: NSNib.Name? { 16 | return NSNib.Name("PreviewViewController") 17 | } 18 | 19 | var viewMIDIPlayer: AVMIDIPlayer! 20 | 21 | var myTimer: Timer? 22 | 23 | @IBOutlet weak var quickLookView: NSView! 24 | @IBOutlet weak var finderView: NSView! 25 | 26 | @IBOutlet weak var finderPlayButton: NSButton! 27 | @IBOutlet weak var finderRestartButton: NSButton! 28 | @IBOutlet weak var finderProgressCircle: NSProgressIndicator! 29 | 30 | @IBOutlet weak var totalTimeLabel: NSTextField! 31 | @IBOutlet weak var currentPlaybackTimeLabel: NSTextField! 32 | @IBOutlet weak var filenameLabel: NSTextField! 33 | @IBOutlet weak var playButton: NSButton! 34 | @IBOutlet weak var restartButton: NSButton! 35 | @IBOutlet weak var theSlider: NSProgressIndicator! 36 | 37 | override func loadView() { 38 | super.loadView() 39 | preferredContentSize = CGSize(width: 800, height: 350) 40 | 41 | finderPlayButton.target = self 42 | finderPlayButton.action = #selector(self.playPause) 43 | finderRestartButton.target = self 44 | finderRestartButton.action = #selector(self.restart) 45 | 46 | playButton.target = self 47 | playButton.action = #selector(self.playPause) 48 | restartButton.target = self 49 | restartButton.action = #selector(self.restart) 50 | } 51 | 52 | @objc func playPause() { 53 | guard let midiPlayer = viewMIDIPlayer else { return } 54 | if (midiPlayer.isPlaying) { 55 | midiPlayer.stop() 56 | } else { 57 | midiPlayer.play(self.completed()) 58 | } 59 | } 60 | 61 | @objc func restart() { 62 | guard let midiPlayer = viewMIDIPlayer else { return } 63 | 64 | midiPlayer.currentPosition = TimeInterval(0) 65 | playButton.state = NSControl.StateValue.on 66 | finderPlayButton.state = NSControl.StateValue.on 67 | midiPlayer.prepareToPlay() 68 | midiPlayer.play ( 69 | self.completed() 70 | ) 71 | } 72 | 73 | func completed() -> AVMIDIPlayerCompletionHandler { 74 | return { 75 | self.playButton.state = .off 76 | self.finderPlayButton.state = .off 77 | } 78 | } 79 | 80 | /* 81 | * Implement this method and set QLSupportsSearchableItems to YES in the Info.plist of the extension if you support CoreSpotlight. 82 | * 83 | func preparePreviewOfSearchableItem(identifier: String, queryString: String?, completionHandler handler: @escaping (Error?) -> Void) { 84 | // Perform any setup necessary in order to prepare the view. 85 | 86 | // Call the completion handler so Quick Look knows that the preview is fully loaded. 87 | // Quick Look will display a loading spinner while the completion handler is not called. 88 | handler(nil) 89 | */ 90 | 91 | func preparePreviewOfFile(at url: URL, completionHandler handler: @escaping (Error?) -> Void) { 92 | do { 93 | viewMIDIPlayer = try AVMIDIPlayer(contentsOf: url, soundBankURL: nil) 94 | viewMIDIPlayer?.prepareToPlay() 95 | theSlider.maxValue = Double(viewMIDIPlayer?.duration ?? 0.0) 96 | 97 | myTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(self.updateDisplay), userInfo: nil, repeats: true) 98 | 99 | finderProgressCircle.maxValue = Double(self.viewMIDIPlayer?.duration ?? 0.0) 100 | filenameLabel.stringValue = url.lastPathComponent 101 | filenameLabel.frame.size.width = CGFloat(filenameLabel.stringValue.count * 13) 102 | currentPlaybackTimeLabel.stringValue = "0:00" 103 | 104 | if let time = self.viewMIDIPlayer?.duration { 105 | let minutes = Int(time / 60) 106 | let seconds = Int((time)) % 60 107 | totalTimeLabel.stringValue = String(format: "%01d:%02d", minutes, seconds) 108 | } 109 | 110 | handler(nil) // Call handler with nil to indicate success 111 | } catch { 112 | handler(error) // Call handler with the caught error 113 | } 114 | } 115 | 116 | override func viewDidAppear() { 117 | if let width = self.view.window?.frame.width, width < 600.0 { 118 | //Finder View 119 | self.finderView.isHidden = false 120 | self.quickLookView.isHidden = true 121 | } else { 122 | // QuickLook Window 123 | self.finderView.isHidden = true 124 | self.quickLookView.isHidden = false 125 | 126 | self.viewMIDIPlayer?.play(self.completed()) 127 | self.playButton.state = .on 128 | } 129 | 130 | super.viewDidAppear() 131 | } 132 | 133 | override func viewWillDisappear() { 134 | if (viewMIDIPlayer!.isPlaying) { 135 | viewMIDIPlayer!.stop() 136 | } 137 | viewMIDIPlayer = nil 138 | myTimer?.invalidate() 139 | super.viewWillDisappear() 140 | } 141 | 142 | @objc func updateDisplay(){ 143 | if viewMIDIPlayer != nil { 144 | if viewMIDIPlayer!.currentPosition <= viewMIDIPlayer!.duration { 145 | theSlider.doubleValue = Double((viewMIDIPlayer!.currentPosition)) 146 | if let currentPosition = self.viewMIDIPlayer?.currentPosition { 147 | let minutes = Int(currentPosition / 60) 148 | let seconds = Int((currentPosition)) % 60 149 | currentPlaybackTimeLabel.stringValue = String(format: "%01d:%02d", minutes, seconds) 150 | finderProgressCircle.doubleValue = Double((viewMIDIPlayer!.currentPosition)) 151 | } 152 | } 153 | } 154 | } 155 | } 156 | 157 | -------------------------------------------------------------------------------- /qlMIDI/Base.lproj/PreviewViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 49 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 139 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | -------------------------------------------------------------------------------- /APPlayMIDI.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 55; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B5051869230C2C9E0024884E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5051868230C2C9E0024884E /* AppDelegate.swift */; }; 11 | B505186B230C2C9E0024884E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B505186A230C2C9E0024884E /* ViewController.swift */; }; 12 | B505186D230C2C9E0024884E /* Document.swift in Sources */ = {isa = PBXBuildFile; fileRef = B505186C230C2C9E0024884E /* Document.swift */; }; 13 | B505186F230C2C9F0024884E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B505186E230C2C9F0024884E /* Assets.xcassets */; }; 14 | B5051872230C2C9F0024884E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B5051870230C2C9F0024884E /* Main.storyboard */; }; 15 | B53CD76F28738D46002A1C80 /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5C2428F2873209700C0CDB1 /* Quartz.framework */; }; 16 | B53CD77228738D46002A1C80 /* PreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53CD77128738D46002A1C80 /* PreviewViewController.swift */; }; 17 | B53CD77428738D46002A1C80 /* PreviewProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53CD77328738D46002A1C80 /* PreviewProvider.swift */; }; 18 | B53CD77728738D46002A1C80 /* PreviewViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B53CD77528738D46002A1C80 /* PreviewViewController.xib */; }; 19 | B53CD77C28738D46002A1C80 /* qlMIDI.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = B53CD76E28738D46002A1C80 /* qlMIDI.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 20 | B53CD78128742F29002A1C80 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B53CD78028742F29002A1C80 /* Media.xcassets */; }; 21 | B560A51D235F7B71007C9033 /* WindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B560A51C235F7B71007C9033 /* WindowController.swift */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | B53CD77A28738D46002A1C80 /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = B505185D230C2C9E0024884E /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = B53CD76D28738D46002A1C80; 30 | remoteInfo = qlMIDI; 31 | }; 32 | /* End PBXContainerItemProxy section */ 33 | 34 | /* Begin PBXCopyFilesBuildPhase section */ 35 | B5C2429E2873209700C0CDB1 /* Embed Foundation Extensions */ = { 36 | isa = PBXCopyFilesBuildPhase; 37 | buildActionMask = 2147483647; 38 | dstPath = ""; 39 | dstSubfolderSpec = 13; 40 | files = ( 41 | B53CD77C28738D46002A1C80 /* qlMIDI.appex in Embed Foundation Extensions */, 42 | ); 43 | name = "Embed Foundation Extensions"; 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | /* End PBXCopyFilesBuildPhase section */ 47 | 48 | /* Begin PBXFileReference section */ 49 | B5051865230C2C9E0024884E /* APPlayMIDI.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = APPlayMIDI.app; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | B5051868230C2C9E0024884E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 51 | B505186A230C2C9E0024884E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 52 | B505186C230C2C9E0024884E /* Document.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Document.swift; sourceTree = ""; }; 53 | B505186E230C2C9F0024884E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 54 | B5051871230C2C9F0024884E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 55 | B5051873230C2C9F0024884E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | B5051874230C2C9F0024884E /* APPlayMIDI.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = APPlayMIDI.entitlements; sourceTree = ""; }; 57 | B53CD76E28738D46002A1C80 /* qlMIDI.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = qlMIDI.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | B53CD77128738D46002A1C80 /* PreviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewViewController.swift; sourceTree = ""; }; 59 | B53CD77328738D46002A1C80 /* PreviewProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewProvider.swift; sourceTree = ""; }; 60 | B53CD77628738D46002A1C80 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PreviewViewController.xib; sourceTree = ""; }; 61 | B53CD77828738D46002A1C80 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 62 | B53CD77928738D46002A1C80 /* qlMIDI.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = qlMIDI.entitlements; sourceTree = ""; }; 63 | B53CD78028742F29002A1C80 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; 64 | B560A51C235F7B71007C9033 /* WindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowController.swift; sourceTree = ""; }; 65 | B5C2428F2873209700C0CDB1 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; }; 66 | /* End PBXFileReference section */ 67 | 68 | /* Begin PBXFrameworksBuildPhase section */ 69 | B5051862230C2C9E0024884E /* Frameworks */ = { 70 | isa = PBXFrameworksBuildPhase; 71 | buildActionMask = 2147483647; 72 | files = ( 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | B53CD76B28738D46002A1C80 /* Frameworks */ = { 77 | isa = PBXFrameworksBuildPhase; 78 | buildActionMask = 2147483647; 79 | files = ( 80 | B53CD76F28738D46002A1C80 /* Quartz.framework in Frameworks */, 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | /* End PBXFrameworksBuildPhase section */ 85 | 86 | /* Begin PBXGroup section */ 87 | B505185C230C2C9E0024884E = { 88 | isa = PBXGroup; 89 | children = ( 90 | B5051867230C2C9E0024884E /* APPlayMIDI */, 91 | B53CD77028738D46002A1C80 /* qlMIDI */, 92 | B5C2428E2873209700C0CDB1 /* Frameworks */, 93 | B5051866230C2C9E0024884E /* Products */, 94 | ); 95 | sourceTree = ""; 96 | }; 97 | B5051866230C2C9E0024884E /* Products */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | B5051865230C2C9E0024884E /* APPlayMIDI.app */, 101 | B53CD76E28738D46002A1C80 /* qlMIDI.appex */, 102 | ); 103 | name = Products; 104 | sourceTree = ""; 105 | }; 106 | B5051867230C2C9E0024884E /* APPlayMIDI */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | B5051868230C2C9E0024884E /* AppDelegate.swift */, 110 | B505186A230C2C9E0024884E /* ViewController.swift */, 111 | B505186C230C2C9E0024884E /* Document.swift */, 112 | B505186E230C2C9F0024884E /* Assets.xcassets */, 113 | B5051870230C2C9F0024884E /* Main.storyboard */, 114 | B560A51C235F7B71007C9033 /* WindowController.swift */, 115 | B5051873230C2C9F0024884E /* Info.plist */, 116 | B5051874230C2C9F0024884E /* APPlayMIDI.entitlements */, 117 | ); 118 | path = APPlayMIDI; 119 | sourceTree = ""; 120 | }; 121 | B53CD77028738D46002A1C80 /* qlMIDI */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | B53CD77128738D46002A1C80 /* PreviewViewController.swift */, 125 | B53CD77328738D46002A1C80 /* PreviewProvider.swift */, 126 | B53CD77528738D46002A1C80 /* PreviewViewController.xib */, 127 | B53CD77828738D46002A1C80 /* Info.plist */, 128 | B53CD77928738D46002A1C80 /* qlMIDI.entitlements */, 129 | B53CD78028742F29002A1C80 /* Media.xcassets */, 130 | ); 131 | path = qlMIDI; 132 | sourceTree = ""; 133 | }; 134 | B5C2428E2873209700C0CDB1 /* Frameworks */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | B5C2428F2873209700C0CDB1 /* Quartz.framework */, 138 | ); 139 | name = Frameworks; 140 | sourceTree = ""; 141 | }; 142 | /* End PBXGroup section */ 143 | 144 | /* Begin PBXNativeTarget section */ 145 | B5051864230C2C9E0024884E /* APPlayMIDI */ = { 146 | isa = PBXNativeTarget; 147 | buildConfigurationList = B5051877230C2C9F0024884E /* Build configuration list for PBXNativeTarget "APPlayMIDI" */; 148 | buildPhases = ( 149 | B5051861230C2C9E0024884E /* Sources */, 150 | B5051862230C2C9E0024884E /* Frameworks */, 151 | B5051863230C2C9E0024884E /* Resources */, 152 | B5C2429E2873209700C0CDB1 /* Embed Foundation Extensions */, 153 | ); 154 | buildRules = ( 155 | ); 156 | dependencies = ( 157 | B53CD77B28738D46002A1C80 /* PBXTargetDependency */, 158 | ); 159 | name = APPlayMIDI; 160 | productName = APPlayMIDI; 161 | productReference = B5051865230C2C9E0024884E /* APPlayMIDI.app */; 162 | productType = "com.apple.product-type.application"; 163 | }; 164 | B53CD76D28738D46002A1C80 /* qlMIDI */ = { 165 | isa = PBXNativeTarget; 166 | buildConfigurationList = B53CD77D28738D46002A1C80 /* Build configuration list for PBXNativeTarget "qlMIDI" */; 167 | buildPhases = ( 168 | B53CD76A28738D46002A1C80 /* Sources */, 169 | B53CD76B28738D46002A1C80 /* Frameworks */, 170 | B53CD76C28738D46002A1C80 /* Resources */, 171 | ); 172 | buildRules = ( 173 | ); 174 | dependencies = ( 175 | ); 176 | name = qlMIDI; 177 | productName = qlMIDI; 178 | productReference = B53CD76E28738D46002A1C80 /* qlMIDI.appex */; 179 | productType = "com.apple.product-type.app-extension"; 180 | }; 181 | /* End PBXNativeTarget section */ 182 | 183 | /* Begin PBXProject section */ 184 | B505185D230C2C9E0024884E /* Project object */ = { 185 | isa = PBXProject; 186 | attributes = { 187 | BuildIndependentTargetsInParallel = YES; 188 | KnownAssetTags = ( 189 | New, 190 | ); 191 | LastSwiftUpdateCheck = 1330; 192 | LastUpgradeCheck = 1500; 193 | ORGANIZATIONNAME = Ben; 194 | TargetAttributes = { 195 | B5051864230C2C9E0024884E = { 196 | CreatedOnToolsVersion = 10.3; 197 | }; 198 | B53CD76D28738D46002A1C80 = { 199 | CreatedOnToolsVersion = 13.3.1; 200 | }; 201 | }; 202 | }; 203 | buildConfigurationList = B5051860230C2C9E0024884E /* Build configuration list for PBXProject "APPlayMIDI" */; 204 | compatibilityVersion = "Xcode 13.0"; 205 | developmentRegion = en; 206 | hasScannedForEncodings = 0; 207 | knownRegions = ( 208 | en, 209 | Base, 210 | ); 211 | mainGroup = B505185C230C2C9E0024884E; 212 | productRefGroup = B5051866230C2C9E0024884E /* Products */; 213 | projectDirPath = ""; 214 | projectRoot = ""; 215 | targets = ( 216 | B5051864230C2C9E0024884E /* APPlayMIDI */, 217 | B53CD76D28738D46002A1C80 /* qlMIDI */, 218 | ); 219 | }; 220 | /* End PBXProject section */ 221 | 222 | /* Begin PBXResourcesBuildPhase section */ 223 | B5051863230C2C9E0024884E /* Resources */ = { 224 | isa = PBXResourcesBuildPhase; 225 | buildActionMask = 2147483647; 226 | files = ( 227 | B505186F230C2C9F0024884E /* Assets.xcassets in Resources */, 228 | B5051872230C2C9F0024884E /* Main.storyboard in Resources */, 229 | ); 230 | runOnlyForDeploymentPostprocessing = 0; 231 | }; 232 | B53CD76C28738D46002A1C80 /* Resources */ = { 233 | isa = PBXResourcesBuildPhase; 234 | buildActionMask = 2147483647; 235 | files = ( 236 | B53CD78128742F29002A1C80 /* Media.xcassets in Resources */, 237 | B53CD77728738D46002A1C80 /* PreviewViewController.xib in Resources */, 238 | ); 239 | runOnlyForDeploymentPostprocessing = 0; 240 | }; 241 | /* End PBXResourcesBuildPhase section */ 242 | 243 | /* Begin PBXSourcesBuildPhase section */ 244 | B5051861230C2C9E0024884E /* Sources */ = { 245 | isa = PBXSourcesBuildPhase; 246 | buildActionMask = 2147483647; 247 | files = ( 248 | B505186B230C2C9E0024884E /* ViewController.swift in Sources */, 249 | B560A51D235F7B71007C9033 /* WindowController.swift in Sources */, 250 | B5051869230C2C9E0024884E /* AppDelegate.swift in Sources */, 251 | B505186D230C2C9E0024884E /* Document.swift in Sources */, 252 | ); 253 | runOnlyForDeploymentPostprocessing = 0; 254 | }; 255 | B53CD76A28738D46002A1C80 /* Sources */ = { 256 | isa = PBXSourcesBuildPhase; 257 | buildActionMask = 2147483647; 258 | files = ( 259 | B53CD77228738D46002A1C80 /* PreviewViewController.swift in Sources */, 260 | B53CD77428738D46002A1C80 /* PreviewProvider.swift in Sources */, 261 | ); 262 | runOnlyForDeploymentPostprocessing = 0; 263 | }; 264 | /* End PBXSourcesBuildPhase section */ 265 | 266 | /* Begin PBXTargetDependency section */ 267 | B53CD77B28738D46002A1C80 /* PBXTargetDependency */ = { 268 | isa = PBXTargetDependency; 269 | target = B53CD76D28738D46002A1C80 /* qlMIDI */; 270 | targetProxy = B53CD77A28738D46002A1C80 /* PBXContainerItemProxy */; 271 | }; 272 | /* End PBXTargetDependency section */ 273 | 274 | /* Begin PBXVariantGroup section */ 275 | B5051870230C2C9F0024884E /* Main.storyboard */ = { 276 | isa = PBXVariantGroup; 277 | children = ( 278 | B5051871230C2C9F0024884E /* Base */, 279 | ); 280 | name = Main.storyboard; 281 | sourceTree = ""; 282 | }; 283 | B53CD77528738D46002A1C80 /* PreviewViewController.xib */ = { 284 | isa = PBXVariantGroup; 285 | children = ( 286 | B53CD77628738D46002A1C80 /* Base */, 287 | ); 288 | name = PreviewViewController.xib; 289 | sourceTree = ""; 290 | }; 291 | /* End PBXVariantGroup section */ 292 | 293 | /* Begin XCBuildConfiguration section */ 294 | B5051875230C2C9F0024884E /* Debug */ = { 295 | isa = XCBuildConfiguration; 296 | buildSettings = { 297 | ALWAYS_SEARCH_USER_PATHS = NO; 298 | CLANG_ANALYZER_NONNULL = YES; 299 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 300 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 301 | CLANG_CXX_LIBRARY = "libc++"; 302 | CLANG_ENABLE_MODULES = YES; 303 | CLANG_ENABLE_OBJC_ARC = YES; 304 | CLANG_ENABLE_OBJC_WEAK = YES; 305 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 306 | CLANG_WARN_BOOL_CONVERSION = YES; 307 | CLANG_WARN_COMMA = YES; 308 | CLANG_WARN_CONSTANT_CONVERSION = YES; 309 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 310 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 311 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 312 | CLANG_WARN_EMPTY_BODY = YES; 313 | CLANG_WARN_ENUM_CONVERSION = YES; 314 | CLANG_WARN_INFINITE_RECURSION = YES; 315 | CLANG_WARN_INT_CONVERSION = YES; 316 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 317 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 318 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 319 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 320 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 321 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 322 | CLANG_WARN_STRICT_PROTOTYPES = YES; 323 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 324 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 325 | CLANG_WARN_UNREACHABLE_CODE = YES; 326 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 327 | CODE_SIGN_IDENTITY = "-"; 328 | COPY_PHASE_STRIP = NO; 329 | DEAD_CODE_STRIPPING = YES; 330 | DEBUG_INFORMATION_FORMAT = dwarf; 331 | ENABLE_STRICT_OBJC_MSGSEND = YES; 332 | ENABLE_TESTABILITY = YES; 333 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 334 | GCC_C_LANGUAGE_STANDARD = gnu11; 335 | GCC_DYNAMIC_NO_PIC = NO; 336 | GCC_NO_COMMON_BLOCKS = YES; 337 | GCC_OPTIMIZATION_LEVEL = 0; 338 | GCC_PREPROCESSOR_DEFINITIONS = ( 339 | "DEBUG=1", 340 | "$(inherited)", 341 | ); 342 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 343 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 344 | GCC_WARN_UNDECLARED_SELECTOR = YES; 345 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 346 | GCC_WARN_UNUSED_FUNCTION = YES; 347 | GCC_WARN_UNUSED_VARIABLE = YES; 348 | MACOSX_DEPLOYMENT_TARGET = 11.5; 349 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 350 | MTL_FAST_MATH = YES; 351 | ONLY_ACTIVE_ARCH = NO; 352 | SDKROOT = macosx; 353 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 354 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 355 | }; 356 | name = Debug; 357 | }; 358 | B5051876230C2C9F0024884E /* Release */ = { 359 | isa = XCBuildConfiguration; 360 | buildSettings = { 361 | ALWAYS_SEARCH_USER_PATHS = NO; 362 | CLANG_ANALYZER_NONNULL = YES; 363 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 364 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 365 | CLANG_CXX_LIBRARY = "libc++"; 366 | CLANG_ENABLE_MODULES = YES; 367 | CLANG_ENABLE_OBJC_ARC = YES; 368 | CLANG_ENABLE_OBJC_WEAK = YES; 369 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 370 | CLANG_WARN_BOOL_CONVERSION = YES; 371 | CLANG_WARN_COMMA = YES; 372 | CLANG_WARN_CONSTANT_CONVERSION = YES; 373 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 374 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 375 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 376 | CLANG_WARN_EMPTY_BODY = YES; 377 | CLANG_WARN_ENUM_CONVERSION = YES; 378 | CLANG_WARN_INFINITE_RECURSION = YES; 379 | CLANG_WARN_INT_CONVERSION = YES; 380 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 381 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 382 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 383 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 384 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 385 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 386 | CLANG_WARN_STRICT_PROTOTYPES = YES; 387 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 388 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 389 | CLANG_WARN_UNREACHABLE_CODE = YES; 390 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 391 | CODE_SIGN_IDENTITY = "-"; 392 | COPY_PHASE_STRIP = NO; 393 | DEAD_CODE_STRIPPING = YES; 394 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 395 | ENABLE_NS_ASSERTIONS = NO; 396 | ENABLE_STRICT_OBJC_MSGSEND = YES; 397 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 398 | GCC_C_LANGUAGE_STANDARD = gnu11; 399 | GCC_NO_COMMON_BLOCKS = YES; 400 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 401 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 402 | GCC_WARN_UNDECLARED_SELECTOR = YES; 403 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 404 | GCC_WARN_UNUSED_FUNCTION = YES; 405 | GCC_WARN_UNUSED_VARIABLE = YES; 406 | MACOSX_DEPLOYMENT_TARGET = 11.5; 407 | MTL_ENABLE_DEBUG_INFO = NO; 408 | MTL_FAST_MATH = YES; 409 | ONLY_ACTIVE_ARCH = NO; 410 | SDKROOT = macosx; 411 | SWIFT_COMPILATION_MODE = wholemodule; 412 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 413 | }; 414 | name = Release; 415 | }; 416 | B5051878230C2C9F0024884E /* Debug */ = { 417 | isa = XCBuildConfiguration; 418 | buildSettings = { 419 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 420 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 421 | CODE_SIGN_ENTITLEMENTS = APPlayMIDI/APPlayMIDI.entitlements; 422 | CODE_SIGN_IDENTITY = "-"; 423 | CODE_SIGN_STYLE = Automatic; 424 | COMBINE_HIDPI_IMAGES = YES; 425 | CURRENT_PROJECT_VERSION = 80; 426 | DEAD_CODE_STRIPPING = YES; 427 | DEVELOPMENT_TEAM = ""; 428 | ENABLE_HARDENED_RUNTIME = YES; 429 | INFOPLIST_FILE = APPlayMIDI/Info.plist; 430 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.music"; 431 | LD_RUNPATH_SEARCH_PATHS = ( 432 | "$(inherited)", 433 | "@executable_path/../Frameworks", 434 | ); 435 | MACOSX_DEPLOYMENT_TARGET = 11.5; 436 | MARKETING_VERSION = 1.14; 437 | PRODUCT_BUNDLE_IDENTIFIER = bensoft.APPlayMIDI; 438 | PRODUCT_NAME = "$(TARGET_NAME)"; 439 | SWIFT_VERSION = 5.0; 440 | }; 441 | name = Debug; 442 | }; 443 | B5051879230C2C9F0024884E /* Release */ = { 444 | isa = XCBuildConfiguration; 445 | buildSettings = { 446 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 447 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 448 | CODE_SIGN_ENTITLEMENTS = APPlayMIDI/APPlayMIDI.entitlements; 449 | CODE_SIGN_IDENTITY = "-"; 450 | CODE_SIGN_STYLE = Automatic; 451 | COMBINE_HIDPI_IMAGES = YES; 452 | CURRENT_PROJECT_VERSION = 80; 453 | DEAD_CODE_STRIPPING = YES; 454 | DEVELOPMENT_TEAM = ""; 455 | ENABLE_HARDENED_RUNTIME = YES; 456 | INFOPLIST_FILE = APPlayMIDI/Info.plist; 457 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.music"; 458 | LD_RUNPATH_SEARCH_PATHS = ( 459 | "$(inherited)", 460 | "@executable_path/../Frameworks", 461 | ); 462 | MACOSX_DEPLOYMENT_TARGET = 11.5; 463 | MARKETING_VERSION = 1.14; 464 | PRODUCT_BUNDLE_IDENTIFIER = bensoft.APPlayMIDI; 465 | PRODUCT_NAME = "$(TARGET_NAME)"; 466 | SWIFT_VERSION = 5.0; 467 | }; 468 | name = Release; 469 | }; 470 | B53CD77E28738D46002A1C80 /* Debug */ = { 471 | isa = XCBuildConfiguration; 472 | buildSettings = { 473 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 474 | CODE_SIGN_ENTITLEMENTS = qlMIDI/qlMIDI.entitlements; 475 | CODE_SIGN_IDENTITY = "-"; 476 | CODE_SIGN_STYLE = Automatic; 477 | CURRENT_PROJECT_VERSION = 80; 478 | DEAD_CODE_STRIPPING = YES; 479 | DEVELOPMENT_TEAM = ""; 480 | ENABLE_HARDENED_RUNTIME = YES; 481 | GENERATE_INFOPLIST_FILE = YES; 482 | INFOPLIST_FILE = qlMIDI/Info.plist; 483 | INFOPLIST_KEY_CFBundleDisplayName = qlMIDI; 484 | INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Ben. All rights reserved."; 485 | LD_RUNPATH_SEARCH_PATHS = ( 486 | "$(inherited)", 487 | "@executable_path/../Frameworks", 488 | "@executable_path/../../../../Frameworks", 489 | ); 490 | MACOSX_DEPLOYMENT_TARGET = 12.0; 491 | MARKETING_VERSION = 1.12; 492 | ONLY_ACTIVE_ARCH = NO; 493 | PRODUCT_BUNDLE_IDENTIFIER = bensoft.APPlayMIDI.qlMIDI; 494 | PRODUCT_NAME = "$(TARGET_NAME)"; 495 | SKIP_INSTALL = YES; 496 | SWIFT_EMIT_LOC_STRINGS = YES; 497 | SWIFT_VERSION = 5.0; 498 | }; 499 | name = Debug; 500 | }; 501 | B53CD77F28738D46002A1C80 /* Release */ = { 502 | isa = XCBuildConfiguration; 503 | buildSettings = { 504 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 505 | CODE_SIGN_ENTITLEMENTS = qlMIDI/qlMIDI.entitlements; 506 | CODE_SIGN_IDENTITY = "-"; 507 | CODE_SIGN_STYLE = Automatic; 508 | CURRENT_PROJECT_VERSION = 80; 509 | DEAD_CODE_STRIPPING = YES; 510 | DEVELOPMENT_TEAM = ""; 511 | ENABLE_HARDENED_RUNTIME = YES; 512 | GENERATE_INFOPLIST_FILE = YES; 513 | INFOPLIST_FILE = qlMIDI/Info.plist; 514 | INFOPLIST_KEY_CFBundleDisplayName = qlMIDI; 515 | INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Ben. All rights reserved."; 516 | LD_RUNPATH_SEARCH_PATHS = ( 517 | "$(inherited)", 518 | "@executable_path/../Frameworks", 519 | "@executable_path/../../../../Frameworks", 520 | ); 521 | MACOSX_DEPLOYMENT_TARGET = 12.0; 522 | MARKETING_VERSION = 1.12; 523 | ONLY_ACTIVE_ARCH = NO; 524 | PRODUCT_BUNDLE_IDENTIFIER = bensoft.APPlayMIDI.qlMIDI; 525 | PRODUCT_NAME = "$(TARGET_NAME)"; 526 | SKIP_INSTALL = YES; 527 | SWIFT_EMIT_LOC_STRINGS = YES; 528 | SWIFT_VERSION = 5.0; 529 | }; 530 | name = Release; 531 | }; 532 | /* End XCBuildConfiguration section */ 533 | 534 | /* Begin XCConfigurationList section */ 535 | B5051860230C2C9E0024884E /* Build configuration list for PBXProject "APPlayMIDI" */ = { 536 | isa = XCConfigurationList; 537 | buildConfigurations = ( 538 | B5051875230C2C9F0024884E /* Debug */, 539 | B5051876230C2C9F0024884E /* Release */, 540 | ); 541 | defaultConfigurationIsVisible = 0; 542 | defaultConfigurationName = Release; 543 | }; 544 | B5051877230C2C9F0024884E /* Build configuration list for PBXNativeTarget "APPlayMIDI" */ = { 545 | isa = XCConfigurationList; 546 | buildConfigurations = ( 547 | B5051878230C2C9F0024884E /* Debug */, 548 | B5051879230C2C9F0024884E /* Release */, 549 | ); 550 | defaultConfigurationIsVisible = 0; 551 | defaultConfigurationName = Release; 552 | }; 553 | B53CD77D28738D46002A1C80 /* Build configuration list for PBXNativeTarget "qlMIDI" */ = { 554 | isa = XCConfigurationList; 555 | buildConfigurations = ( 556 | B53CD77E28738D46002A1C80 /* Debug */, 557 | B53CD77F28738D46002A1C80 /* Release */, 558 | ); 559 | defaultConfigurationIsVisible = 0; 560 | defaultConfigurationName = Release; 561 | }; 562 | /* End XCConfigurationList section */ 563 | }; 564 | rootObject = B505185D230C2C9E0024884E /* Project object */; 565 | } 566 | -------------------------------------------------------------------------------- /APPlayMIDI/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 603 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | --------------------------------------------------------------------------------