├── .gitignore ├── LICENSE ├── MicroPrint UI ├── Base.lproj │ └── Main.storyboard ├── Images.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── microprint1024.png │ │ ├── microprint128.png │ │ ├── microprint16.png │ │ ├── microprint16@2x.png │ │ ├── microprint256-1.png │ │ ├── microprint256.png │ │ ├── microprint32.png │ │ ├── microprint512-1.png │ │ ├── microprint512.png │ │ └── microprint64.png │ ├── Contents.json │ ├── Micro.imageset │ │ ├── Contents.json │ │ ├── Micro.png │ │ └── Micro@2x.png │ └── Printbed.imageset │ │ ├── Contents.json │ │ ├── Printbed.png │ │ └── Printbed@2x.png ├── Info.plist ├── TFPAppleScriptSupport.h ├── TFPAppleScriptSupport.m ├── TFPApplicationDelegate.h ├── TFPApplicationDelegate.m ├── TFPBacklashSettingsViewController.h ├── TFPBacklashSettingsViewController.m ├── TFPBedLevelCalibrationViewController.h ├── TFPBedLevelCalibrationViewController.m ├── TFPBedLevelSettingsViewController.h ├── TFPBedLevelSettingsViewController.m ├── TFPCalibrationViewController.h ├── TFPCalibrationViewController.m ├── TFPConsoleViewController.h ├── TFPConsoleViewController.m ├── TFPGCodeDocument.h ├── TFPGCodeDocument.m ├── TFPPrintSettingsViewController.h ├── TFPPrintSettingsViewController.m ├── TFPPrinterCollectionViewItem.h ├── TFPPrinterCollectionViewItem.m ├── TFPPrinterListCollectionView.h ├── TFPPrinterListCollectionView.m ├── TFPPrinterListViewController.h ├── TFPPrinterListViewController.m ├── TFPPrinterOperationsViewController.h ├── TFPPrinterOperationsViewController.m ├── TFPPrintingProgressViewController.h ├── TFPPrintingProgressViewController.m ├── TFPScriptManager.h ├── TFPScriptManager.m ├── TFPUIExtras.h ├── TFPUIExtras.m ├── TFPVisualPrintProgressView.h ├── TFPVisualPrintProgressView.m ├── TFPZeroHeadViewController.h ├── TFPZeroHeadViewController.m └── main.m ├── README.md ├── microprint.xcodeproj └── project.pbxproj └── microprint ├── .DS_Store ├── MAKVONotificationCenter.h ├── MAKVONotificationCenter.m ├── MicroPrint.sdef ├── ORSSerialPort.h ├── ORSSerialPort.m ├── ORSSerialPortManager.h ├── ORSSerialPortManager.m ├── ORSSerialRequest.h ├── ORSSerialRequest.m ├── ProfileTranslations.rtf ├── Sparkle.framework ├── Headers ├── Modules ├── PrivateHeaders ├── Resources ├── Sparkle └── Versions │ ├── A │ ├── Headers │ │ ├── SUAppcast.h │ │ ├── SUAppcastItem.h │ │ ├── SUErrors.h │ │ ├── SUExport.h │ │ ├── SUStandardVersionComparator.h │ │ ├── SUUpdater.h │ │ ├── SUVersionComparisonProtocol.h │ │ ├── SUVersionDisplayProtocol.h │ │ └── Sparkle.h │ ├── Modules │ │ └── module.modulemap │ ├── PrivateHeaders │ │ └── SUUnarchiver.h │ ├── Resources │ │ ├── Autoupdate.app │ │ │ └── Contents │ │ │ │ ├── Info.plist │ │ │ │ ├── MacOS │ │ │ │ └── Autoupdate │ │ │ │ ├── PkgInfo │ │ │ │ └── Resources │ │ │ │ ├── AppIcon.icns │ │ │ │ ├── SUStatus.nib │ │ │ │ ├── ar.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── cs.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── da.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── de.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── el.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── en.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── es.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── fr.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── is.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── it.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── ja.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── ko.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── nb.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── nl.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── pl.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── pt_BR.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── pt_PT.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── ro.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── ru.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── sk.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── sl.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── sv.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── th.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── tr.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── uk.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ ├── zh_CN.lproj │ │ │ │ └── Sparkle.strings │ │ │ │ └── zh_TW.lproj │ │ │ │ └── Sparkle.strings │ │ ├── Info.plist │ │ ├── SUModelTranslation.plist │ │ ├── SUStatus.nib │ │ ├── ar.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── cs.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── da.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── de.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── el.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── en.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── es.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── fr.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── fr_CA.lproj │ │ ├── is.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── it.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── ja.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── ko.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── nb.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── nl.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── pl.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── pt.lproj │ │ ├── pt_BR.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── pt_PT.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── ro.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── ru.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── sk.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── sl.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── sv.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── th.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── tr.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── uk.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ ├── zh_CN.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ │ └── zh_TW.lproj │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ ├── SUUpdateAlert.nib │ │ │ ├── SUUpdatePermissionPrompt.nib │ │ │ └── Sparkle.strings │ └── Sparkle │ └── Current ├── TFAsyncOperationCoalescer.h ├── TFAsyncOperationCoalescer.m ├── TFDataBuilder.h ├── TFDataBuilder.m ├── TFP3DVector.h ├── TFP3DVector.m ├── TFPApplicationDebug.h ├── TFPApplicationDebug.m ├── TFPBedLevelCalibration.h ├── TFPBedLevelCalibration.m ├── TFPBedLevelCompensator.h ├── TFPBedLevelCompensator.m ├── TFPDryRunPrinter.h ├── TFPDryRunPrinter.m ├── TFPDryRunPrinterConnection.h ├── TFPDryRunPrinterConnection.m ├── TFPExtras.h ├── TFPExtras.m ├── TFPExtrusionOperation.h ├── TFPExtrusionOperation.m ├── TFPFilament.h ├── TFPFilament.m ├── TFPGCode.h ├── TFPGCode.m ├── TFPGCodeHelpers.h ├── TFPGCodeHelpers.m ├── TFPGCodeProgram.h ├── TFPGCodeProgram.m ├── TFPOperation.h ├── TFPOperation.m ├── TFPPrintJob.h ├── TFPPrintJob.m ├── TFPPrintParameters.h ├── TFPPrintParameters.m ├── TFPPrintStatusController.h ├── TFPPrintStatusController.m ├── TFPPrinter+VirtualEEPROM.h ├── TFPPrinter+VirtualEEPROM.m ├── TFPPrinter.h ├── TFPPrinter.m ├── TFPPrinterConnection.h ├── TFPPrinterConnection.m ├── TFPPrinterHelpers.h ├── TFPPrinterHelpers.m ├── TFPPrinterManager.h ├── TFPPrinterManager.m ├── TFPRaiseHeadOperation.h ├── TFPRaiseHeadOperation.m ├── TFPSlicerProfile.h ├── TFPSlicerProfile.m ├── TFPStopwatch.h ├── TFPStopwatch.m ├── TFPZeroBedOperation.h ├── TFPZeroBedOperation.m ├── TFStringScanner.h ├── TFStringScanner.m ├── TFTimer.h └── TFTimer.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | #Pods/ 27 | microprint.xcodeproj/project.xcworkspace/contents.xcworkspacedata 28 | .DS_Store 29 | microprint.xcodeproj/project.xcworkspace 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Tomas Franzén 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "microprint16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "microprint16@2x.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "microprint32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "microprint64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "microprint128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "microprint256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "microprint256-1.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "microprint512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "microprint512-1.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "microprint1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint1024.png -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint128.png -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint16.png -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint16@2x.png -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint256-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint256-1.png -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint256.png -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint32.png -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint512-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint512-1.png -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint512.png -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/MicroPrint UI/Images.xcassets/AppIcon.appiconset/microprint64.png -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/Micro.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Micro.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Micro@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/Micro.imageset/Micro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/MicroPrint UI/Images.xcassets/Micro.imageset/Micro.png -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/Micro.imageset/Micro@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/MicroPrint UI/Images.xcassets/Micro.imageset/Micro@2x.png -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/Printbed.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Printbed.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Printbed@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/Printbed.imageset/Printbed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/MicroPrint UI/Images.xcassets/Printbed.imageset/Printbed.png -------------------------------------------------------------------------------- /MicroPrint UI/Images.xcassets/Printbed.imageset/Printbed@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/MicroPrint UI/Images.xcassets/Printbed.imageset/Printbed@2x.png -------------------------------------------------------------------------------- /MicroPrint UI/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppTransportSecurity 6 | 7 | NSExceptionDomains 8 | 9 | tomasf.se 10 | 11 | NSExceptionAllowsInsecureHTTPLoads 12 | 13 | 14 | 15 | NSAllowsArbitraryLoads 16 | 17 | 18 | CFBundleDevelopmentRegion 19 | en 20 | CFBundleDocumentTypes 21 | 22 | 23 | CFBundleTypeExtensions 24 | 25 | gcode 26 | 27 | CFBundleTypeIconFile 28 | 29 | CFBundleTypeName 30 | G-code file 31 | CFBundleTypeOSTypes 32 | 33 | ???? 34 | 35 | CFBundleTypeRole 36 | Viewer 37 | NSDocumentClass 38 | TFPGCodeDocument 39 | 40 | 41 | CFBundleExecutable 42 | $(EXECUTABLE_NAME) 43 | CFBundleIdentifier 44 | $(PRODUCT_BUNDLE_IDENTIFIER) 45 | CFBundleInfoDictionaryVersion 46 | 6.0 47 | CFBundleName 48 | $(PRODUCT_NAME) 49 | CFBundlePackageType 50 | APPL 51 | SUFeedURL 52 | http://tomasf.se/projects/microprint/appcast.xml 53 | SUEnableAutomaticChecks 54 | 55 | SUScheduledCheckInterval 56 | 86400 57 | CFBundleShortVersionString 58 | 201509301800 59 | CFBundleSignature 60 | ???? 61 | CFBundleVersion 62 | 201509301800 63 | LSMinimumSystemVersion 64 | $(MACOSX_DEPLOYMENT_TARGET) 65 | NSAppleScriptEnabled 66 | 67 | NSHumanReadableCopyright 68 | Copyright © 2015 Tomas Franzén. All rights reserved. 69 | NSMainStoryboardFile 70 | Main 71 | NSPrincipalClass 72 | NSApplication 73 | OSAScriptingDefinition 74 | MicroPrint.sdef 75 | 76 | 77 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPAppleScriptSupport.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPAppleScriptSupport.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Tue 2015-07-21. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TFPPrintSettingsViewController.h" 11 | 12 | @interface TFPPrintSettingsViewController (AppleScriptSupport) 13 | @end 14 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPApplicationDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // MicroPrint UI 4 | // 5 | // Created by Tomas Franzén on Mon 2015-07-13. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TFPApplicationDelegate : NSObject 12 | @end 13 | 14 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPApplicationDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // MicroPrint UI 4 | // 5 | // Created by Tomas Franzén on Mon 2015-07-13. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPApplicationDelegate.h" 10 | #import "TFPPrinterManager.h" 11 | #import "TFPPrinter.h" 12 | #import "TFPDryRunPrinter.h" 13 | #import "TFPBedLevelCompensator.h" 14 | 15 | #import "TFPExtras.h" 16 | 17 | 18 | @interface TFPApplicationDelegate () 19 | @property NSWindow *mainWindow; 20 | @property TFPPrinterContext *debugContext; 21 | @property (copy) void(^debugCancelBlock)(); 22 | @end 23 | 24 | 25 | @implementation TFPApplicationDelegate 26 | 27 | 28 | - (void)applicationDidFinishLaunching:(NSNotification *)notification { 29 | self.mainWindow = [NSApp windows].firstObject; 30 | } 31 | 32 | 33 | - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender { 34 | [self.mainWindow makeKeyAndOrderFront:nil]; 35 | return NO; 36 | } 37 | 38 | 39 | - (IBAction)openMainWindow:(id)sender { 40 | [self.mainWindow makeKeyAndOrderFront:nil]; 41 | } 42 | 43 | 44 | @end -------------------------------------------------------------------------------- /MicroPrint UI/TFPBacklashSettingsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPBacklashSettings.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Thu 2015-07-16. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TFPPrinter.h" 11 | 12 | 13 | @interface TFPBacklashSettingsViewController : NSViewController 14 | @property TFPPrinter *printer; 15 | @end 16 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPBacklashSettingsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPBacklashSettings.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Thu 2015-07-16. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPBacklashSettingsViewController.h" 10 | 11 | #import "MAKVONotificationCenter.h" 12 | 13 | 14 | @interface TFPBacklashSettingsViewController () 15 | @property double xValue; 16 | @property double yValue; 17 | @property double speed; 18 | 19 | @property BOOL hasChanges; 20 | @end 21 | 22 | 23 | @implementation TFPBacklashSettingsViewController 24 | 25 | - (void)viewDidAppear { 26 | [super viewDidAppear]; 27 | __weak __typeof__(self) weakSelf = self; 28 | 29 | [self addObserver:self keyPath:@"printer.backlashValues" options:NSKeyValueObservingOptionInitial block:^(MAKVONotification *notification) { 30 | if(!weakSelf.hasChanges) { 31 | weakSelf.xValue = weakSelf.printer.backlashValues.x; 32 | weakSelf.yValue = weakSelf.printer.backlashValues.y; 33 | weakSelf.speed = weakSelf.printer.backlashValues.speed; 34 | weakSelf.hasChanges = NO; 35 | } 36 | }]; 37 | 38 | [self addObserver:self keyPath:@[@"xValue", @"yValue", @"speed"] options:0 block:^(MAKVONotification *notification) { 39 | weakSelf.hasChanges = YES; 40 | }]; 41 | } 42 | 43 | 44 | - (IBAction)apply:(id)sender { 45 | TFPBacklashValues values = {.x = self.xValue, .y = self.yValue, .speed = self.speed}; 46 | self.printer.backlashValues = values; 47 | self.hasChanges = NO; 48 | } 49 | 50 | 51 | @end -------------------------------------------------------------------------------- /MicroPrint UI/TFPBedLevelCalibrationViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPBedLevelCalibrationViewController.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sat 2015-07-18. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | @class TFPPrinter; 11 | @class TFPBedLevelSettingsViewController; 12 | 13 | @interface TFPBedLevelCalibrationViewController : NSViewController 14 | @property TFPPrinter *printer; 15 | @property (weak) TFPBedLevelSettingsViewController *bedLevelSettingsViewController; 16 | @end 17 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPBedLevelCalibrationViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPBedLevelCalibrationViewController.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sat 2015-07-18. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPBedLevelCalibrationViewController.h" 10 | #import "TFPBedLevelCalibration.h" 11 | #import "TFPExtras.h" 12 | #import "TFPBedLevelSettingsViewController.h" 13 | 14 | 15 | @interface TFPBedLevelCalibrationViewController () 16 | @property TFPBedLevelCalibration *operation; 17 | @property IBOutlet NSTabView *tabView; 18 | @property IBOutlet NSStepper *levelStepper; 19 | @property TFPBedLevelCalibrationCorner currentCorner; 20 | 21 | @property double startLevel; 22 | @end 23 | 24 | 25 | @implementation TFPBedLevelCalibrationViewController 26 | 27 | 28 | - (void)switchToMovingMode { 29 | [self.tabView selectTabViewItemWithIdentifier:@"moving"]; 30 | } 31 | 32 | 33 | - (void)switchToAdjustmentMode { 34 | [self.tabView selectTabViewItemWithIdentifier:@"adjustment"]; 35 | } 36 | 37 | 38 | - (NSString*)cornerString { 39 | return @{@(TFPBedLevelCalibrationCornerBackLeft): @"Back-left corner", 40 | @(TFPBedLevelCalibrationCornerBackRight): @"Back-right corner", 41 | @(TFPBedLevelCalibrationCornerBackFrontRight): @"Front-right corner", 42 | @(TFPBedLevelCalibrationCornerBackFrontLeft): @"Front-left corner", 43 | @(TFPBedLevelCalibrationCornerCenter): @"Center" 44 | }[@(self.currentCorner)]; 45 | } 46 | 47 | 48 | + (NSSet *)keyPathsForValuesAffectingCornerString { 49 | return @[@"currentCorner"].tf_set; 50 | } 51 | 52 | 53 | - (NSString*)continueString { 54 | if(self.currentCorner == TFPBedLevelCalibrationCornerLast) { 55 | return @"Finish Calibration"; 56 | }else{ 57 | return @"Next Corner"; 58 | } 59 | } 60 | 61 | 62 | + (NSSet *)keyPathsForValuesAffectingContinueString { 63 | return @[@"currentCorner"].tf_set; 64 | } 65 | 66 | 67 | - (IBAction)stepperAction:(NSStepper*)stepper { 68 | if(stepper.doubleValue < 0) { 69 | [self.operation adjustDown]; 70 | }else{ 71 | [self.operation adjustUp]; 72 | } 73 | stepper.doubleValue = 0; 74 | } 75 | 76 | 77 | - (void)viewDidLoad { 78 | [super viewDidLoad]; 79 | BOOL alt = !!([NSEvent modifierFlags] & NSAlternateKeyMask); 80 | self.startLevel = alt ? 50 : 3; 81 | } 82 | 83 | 84 | - (void)viewDidAppear { 85 | [super viewDidAppear]; 86 | __weak __typeof__(self) weakSelf = self; 87 | 88 | if(self.operation) { 89 | return; 90 | } 91 | 92 | self.operation = [[TFPBedLevelCalibration alloc] initWithPrinter:self.printer]; 93 | [self.operation startAtLevel:self.startLevel heightTarget:0.3]; 94 | 95 | self.operation.didStartMovingHandler = ^{ 96 | [weakSelf switchToMovingMode]; 97 | }; 98 | 99 | self.operation.didStopAtCornerHandler = ^(TFPBedLevelCalibrationCorner corner){ 100 | weakSelf.currentCorner = corner; 101 | [weakSelf switchToAdjustmentMode]; 102 | }; 103 | 104 | self.operation.didFinishHandler = ^{ 105 | [weakSelf dismissController:nil]; 106 | }; 107 | 108 | [self.view.window makeFirstResponder:self.levelStepper]; 109 | } 110 | 111 | 112 | - (BOOL)performKeyEquivalent:(NSEvent *)theEvent { 113 | NSString *string = theEvent.characters; 114 | unichar c = string.length ? [string characterAtIndex:0] : 0; 115 | 116 | if(c == NSUpArrowFunctionKey || c == NSDownArrowFunctionKey) { 117 | [self.levelStepper keyUp:theEvent]; 118 | return YES; 119 | } else { 120 | return NO; 121 | } 122 | } 123 | 124 | 125 | - (IBAction)next:(id)sender { 126 | [self.operation continue]; 127 | } 128 | 129 | 130 | - (IBAction)cancel:(id)sender { 131 | [self.operation stop]; 132 | [self dismissController:nil]; 133 | } 134 | 135 | 136 | @end -------------------------------------------------------------------------------- /MicroPrint UI/TFPBedLevelSettingsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPBedLevelSettingsViewController.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Thu 2015-07-16. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | @import AppKit; 10 | #import "TFPCalibrationViewController.h" 11 | #import "TFPPrinter.h" 12 | 13 | @interface TFPBedLevelSettingsViewController : TFPCalibrationViewController 14 | @end 15 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPBedLevelSettingsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPBedLevelSettingsViewController.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Thu 2015-07-16. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPBedLevelSettingsViewController.h" 10 | #import "TFPBedLevelCalibrationViewController.h" 11 | #import "MAKVONotificationCenter.h" 12 | 13 | 14 | @interface TFPBedLevelSettingsViewController () 15 | @property double backLeftOffset; 16 | @property double backRightOffset; 17 | @property double frontRightOffset; 18 | @property double frontLeftOffset; 19 | @property double commonOffset; 20 | 21 | @property BOOL hasChanges; 22 | 23 | @property NSWindowController *calibrationWindowController; 24 | @end 25 | 26 | 27 | @implementation TFPBedLevelSettingsViewController 28 | 29 | 30 | - (void)viewDidAppear { 31 | [super viewDidAppear]; 32 | __weak __typeof__(self) weakSelf = self; 33 | 34 | [self addObserver:self keyPath:@"printer.bedLevelOffsets" options:NSKeyValueObservingOptionInitial block:^(MAKVONotification *notification) { 35 | if(!weakSelf.hasChanges) { 36 | weakSelf.backLeftOffset = weakSelf.printer.bedLevelOffsets.backLeft; 37 | weakSelf.backRightOffset = weakSelf.printer.bedLevelOffsets.backRight; 38 | weakSelf.frontRightOffset = weakSelf.printer.bedLevelOffsets.frontRight; 39 | weakSelf.frontLeftOffset = weakSelf.printer.bedLevelOffsets.frontLeft; 40 | weakSelf.commonOffset = weakSelf.printer.bedLevelOffsets.common; 41 | weakSelf.hasChanges = NO; 42 | } 43 | }]; 44 | 45 | [self addObserver:self keyPath:@[@"backLeftOffset", @"backRightOffset", @"frontRightOffset", @"frontLeftOffset", @"commonOffset"] options:0 block:^(MAKVONotification *notification) { 46 | weakSelf.hasChanges = YES; 47 | }]; 48 | } 49 | 50 | 51 | - (IBAction)apply:(id)sender { 52 | TFPBedLevelOffsets offsets; 53 | offsets.backLeft = self.backLeftOffset; 54 | offsets.backRight = self.backRightOffset; 55 | offsets.frontRight = self.frontRightOffset; 56 | offsets.frontLeft = self.frontLeftOffset; 57 | offsets.common = self.commonOffset; 58 | 59 | self.printer.bedLevelOffsets = offsets; 60 | self.hasChanges = NO; 61 | } 62 | 63 | 64 | - (IBAction)interactiveCalibration:(id)sender { 65 | NSWindowController *windowController = [self.storyboard instantiateControllerWithIdentifier:@"BedLevelCalibrationWindowController"]; 66 | TFPBedLevelCalibrationViewController *viewController = (TFPBedLevelCalibrationViewController*)windowController.contentViewController; 67 | viewController.printer = self.printer; 68 | viewController.bedLevelSettingsViewController = self; 69 | 70 | [self presentViewControllerAsSheet:viewController]; 71 | } 72 | 73 | 74 | - (void)prepareForSegue:(NSStoryboardSegue *)segue sender:(id)sender { 75 | [(TFPCalibrationViewController*)segue.destinationController setPrinter:self.printer]; 76 | } 77 | 78 | 79 | @end -------------------------------------------------------------------------------- /MicroPrint UI/TFPCalibrationViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPCalibrationViewController.h 3 | // microprint 4 | // 5 | // Created by William Waggoner on 8/2/15. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TFPPrinter.h" 11 | 12 | @interface TFPCalibrationViewController : NSViewController 13 | @property TFPPrinter *printer; 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPCalibrationViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPCalibrationViewController.m 3 | // microprint 4 | // 5 | // Created by William Waggoner on 8/2/15. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPCalibrationViewController.h" 10 | 11 | @interface TFPCalibrationViewController () 12 | 13 | @end 14 | 15 | @implementation TFPCalibrationViewController 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPConsoleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPConsoleViewController.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Thu 2015-07-30. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TFPPrinter.h" 11 | 12 | 13 | @interface TFPConsoleViewController : NSViewController 14 | @property TFPPrinter *printer; 15 | @end 16 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPConsoleViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPConsoleViewController.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Thu 2015-07-30. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPConsoleViewController.h" 10 | #import "TFPExtras.h" 11 | 12 | static const NSUInteger consoleMax = 100000; 13 | static const NSUInteger consoleTrim = consoleMax / 10; 14 | 15 | 16 | @interface TFPConsoleViewController () 17 | @property IBOutlet NSTextView *textView; 18 | @property IBOutlet NSTextField *inputField; 19 | @property unsigned long consoleLength; 20 | @end 21 | 22 | 23 | 24 | @implementation TFPConsoleViewController 25 | 26 | 27 | - (void)appendLine:(NSString*)line attributes:(NSDictionary*)attrs { 28 | line = [line stringByAppendingString:@"\n"]; 29 | NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:line attributes:attrs]; 30 | [self.textView.textStorage appendAttributedString:attributedString]; 31 | 32 | [self.textView scrollRangeToVisible: NSMakeRange(self.textView.string.length, 0)]; 33 | 34 | self.consoleLength += attributedString.length; 35 | 36 | if (self.consoleLength > consoleMax) { 37 | [self.textView.textStorage deleteCharactersInRange: NSMakeRange(0, consoleTrim)]; 38 | self.consoleLength = self.textView.textStorage.length; 39 | } 40 | } 41 | 42 | 43 | - (void)viewDidAppear { 44 | [super viewDidAppear]; 45 | __weak __typeof__(self) weakSelf = self; 46 | 47 | self.consoleLength = 0; 48 | 49 | NSColor *noticeColor = [NSColor colorWithCalibratedRed:0.625 green:0.000 blue:0.026 alpha:1.000]; 50 | 51 | NSDictionary *incomingAttributes = @{NSFontAttributeName: [NSFont fontWithName:@"Menlo" size:13]}; 52 | NSDictionary *outgoingAttributes = @{NSFontAttributeName: [NSFont fontWithName:@"Menlo-Bold" size:13]}; 53 | NSDictionary *noticeAttributes = @{NSFontAttributeName: [NSFont fontWithName:@"Menlo-Italic" size:13], NSForegroundColorAttributeName: noticeColor}; 54 | 55 | self.printer.incomingCodeBlock = ^(NSString *line) { 56 | [weakSelf appendLine:line attributes:incomingAttributes]; 57 | }; 58 | self.printer.outgoingCodeBlock = ^(NSString *line) { 59 | [weakSelf appendLine:line attributes:outgoingAttributes]; 60 | }; 61 | self.printer.noticeBlock = ^(NSString *line) { 62 | [weakSelf appendLine:line attributes:noticeAttributes]; 63 | }; 64 | 65 | self.textView.string = @""; 66 | [self.view.window makeFirstResponder:self.inputField]; 67 | } 68 | 69 | 70 | - (void)viewDidDisappear { 71 | [super viewDidDisappear]; 72 | self.printer.incomingCodeBlock = nil; 73 | self.printer.outgoingCodeBlock = nil; 74 | } 75 | 76 | 77 | - (IBAction)fieldAction:(id)sender { 78 | __block BOOL valid = YES; 79 | 80 | NSArray *codes = [[self.inputField.stringValue componentsSeparatedByString:@"\n"] tf_mapWithBlock:^TFPGCode*(NSString *line) { 81 | TFPGCode *code = [TFPGCode codeWithString:line]; 82 | if(!code) { 83 | valid = NO; 84 | } 85 | return code; 86 | }]; 87 | 88 | if(valid) { 89 | for(TFPGCode *code in codes) { 90 | [self.printer sendGCode:code responseHandler:nil]; 91 | } 92 | self.inputField.stringValue = @""; 93 | } else { 94 | NSBeep(); 95 | } 96 | } 97 | 98 | 99 | - (IBAction)clearLog:(id)sender { 100 | [self.textView setString:@""]; 101 | } 102 | 103 | 104 | @end -------------------------------------------------------------------------------- /MicroPrint UI/TFPGCodeDocument.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPGCodeDocument.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Mon 2015-07-13. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TFPFilament.h" 11 | #import "TFPGCodeHelpers.h" 12 | #import "TFPSlicerProfile.h" 13 | 14 | @class TFP3DVector, TFPPrinter; 15 | 16 | 17 | @interface TFPGCodeDocument : NSDocument 18 | @property TFPGCodeProgram *program; 19 | 20 | @property (readonly) BOOL hasBoundingBox; 21 | @property (readonly) TFPCuboid boundingBox; 22 | @property (readonly) TFPSlicerProfile *slicerProfile; 23 | 24 | @property TFPFilamentType filamentType; 25 | @property NSNumber *temperature; 26 | @property BOOL useThermalBonding; 27 | 28 | @property TFPPrinter *selectedPrinter; 29 | @property NSURL *completionScriptURL; 30 | 31 | - (void)saveSettings; 32 | @end -------------------------------------------------------------------------------- /MicroPrint UI/TFPPrintSettingsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrintSettingsViewController.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Mon 2015-07-13. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | @class TFPGCodeDocument; 11 | 12 | @interface TFPPrintSettingsViewController : NSViewController 13 | @property (strong) TFPGCodeDocument *document; 14 | @end 15 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPPrinterCollectionViewItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrinterCollectionViewItem.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Tue 2015-07-14. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TFPPrinterCollectionViewItem : NSCollectionViewItem 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPPrinterListCollectionView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrinterListCollectionView.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Thu 2015-07-30. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TFPPrinterListCollectionView : NSCollectionView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPPrinterListCollectionView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrinterListCollectionView.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Thu 2015-07-30. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPPrinterListCollectionView.h" 10 | 11 | @implementation TFPPrinterListCollectionView 12 | 13 | - (NSCollectionViewItem *)newItemForRepresentedObject:(id)object { 14 | NSCollectionViewItem *item = [[NSStoryboard storyboardWithName:@"Main" bundle:nil] instantiateControllerWithIdentifier:@"printerItemPrototype"]; 15 | item.representedObject = object; 16 | return item; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPPrinterListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // MicroPrint UI 4 | // 5 | // Created by Tomas Franzén on Mon 2015-07-13. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TFPPrinterListViewController : NSViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPPrinterListViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // MicroPrint UI 4 | // 5 | // Created by Tomas Franzén on Mon 2015-07-13. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPPrinterListViewController.h" 10 | #import "TFPPrinterManager.h" 11 | #import "TFPDryRunPrinter.h" 12 | #import "TFPApplicationDelegate.h" 13 | #import "TFPExtras.h" 14 | 15 | 16 | @interface TFPPrinterListViewController () 17 | @property IBOutlet NSCollectionView *collectionView; 18 | @property TFPPrinterManager *printerManager; 19 | 20 | @property IBOutlet NSPopUpButton *recentsButton; 21 | @end 22 | 23 | 24 | 25 | @implementation TFPPrinterListViewController 26 | 27 | - (void)viewDidLoad { 28 | [super viewDidLoad]; 29 | 30 | self.collectionView.itemPrototype = [self.storyboard instantiateControllerWithIdentifier:@"printerItemPrototype"]; 31 | self.collectionView.maxItemSize = CGSizeMake(0, 100); 32 | 33 | self.printerManager = [TFPPrinterManager sharedManager]; 34 | } 35 | 36 | 37 | - (void)openRecentDocument:(NSMenuItem*)menuItem { 38 | NSURL *URL = menuItem.representedObject; 39 | [[NSDocumentController sharedDocumentController] openDocumentWithContentsOfURL:URL display:YES completionHandler:^(NSDocument * _Nullable document, BOOL documentWasAlreadyOpen, NSError * _Nullable error) { 40 | 41 | }]; 42 | } 43 | 44 | 45 | - (void)menuNeedsUpdate:(NSMenu *)menu { 46 | [menu removeAllItems]; 47 | 48 | NSMenuItem *titleItem = [[NSMenuItem alloc] initWithTitle:@"Recent Files" action:nil keyEquivalent:@""]; 49 | [menu addItem:titleItem]; 50 | 51 | NSArray *newItems = [[[NSDocumentController sharedDocumentController] recentDocumentURLs] tf_mapWithBlock:^NSMenuItem*(NSURL *URL) { 52 | NSDictionary *resourceValues = [URL resourceValuesForKeys:@[NSURLEffectiveIconKey, NSURLLocalizedNameKey] error:nil]; 53 | NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:resourceValues[NSURLLocalizedNameKey] action:@selector(openRecentDocument:) keyEquivalent:@""]; 54 | item.target = self; 55 | item.representedObject = URL; 56 | 57 | NSImage *image = [resourceValues[NSURLEffectiveIconKey] copy]; 58 | image.size = CGSizeMake(16, 16); 59 | item.image = image; 60 | 61 | return item; 62 | }]; 63 | 64 | for(NSMenuItem *newItem in newItems){ 65 | [menu addItem:newItem]; 66 | } 67 | } 68 | 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPPrinterOperationsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPFilamentOperationsViewController.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Tue 2015-07-14. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | @class TFPPrinter; 11 | 12 | @interface TFPPrinterOperationsViewController : NSViewController 13 | @property TFPPrinter *printer; 14 | @end 15 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPPrinterOperationsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPFilamentOperationsViewController.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Tue 2015-07-14. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPPrinterOperationsViewController.h" 10 | #import "TFPExtrusionOperation.h" 11 | #import "TFPRaiseHeadOperation.h" 12 | #import "TFPZeroBedOperation.h" 13 | #import "TFPExtras.h" 14 | 15 | 16 | @interface TFPPrinterOperationsViewController () 17 | @property IBOutletCollection (NSButton) NSArray *actionButtons; 18 | @property NSArray *actionButtonTitles; 19 | 20 | @property IBOutlet NSButton *retractButton; 21 | @property IBOutlet NSButton *extrudeButton; 22 | @property IBOutlet NSButton *raiseButton; 23 | @property IBOutlet NSButton *closeButton; 24 | 25 | @property IBOutlet NSProgressIndicator *progressIndicator; 26 | @property IBOutlet NSTextField *statusLabel; 27 | 28 | @property TFPOperation *operation; 29 | @end 30 | 31 | 32 | @implementation TFPPrinterOperationsViewController 33 | 34 | 35 | - (void)startRetract:(BOOL)retract { 36 | __weak __typeof__(self) weakSelf = self; 37 | 38 | TFPExtrusionOperation *operation = [[TFPExtrusionOperation alloc] initWithPrinter:self.printer retraction:retract]; 39 | self.operation = operation; 40 | self.progressIndicator.hidden = NO; 41 | [weakSelf.progressIndicator setIndeterminate:NO]; 42 | [weakSelf.progressIndicator startAnimation:nil]; 43 | weakSelf.statusLabel.stringValue = @"Preparing…"; 44 | 45 | operation.preparationProgressBlock = ^(double fraction){ 46 | weakSelf.progressIndicator.doubleValue = fraction; 47 | }; 48 | 49 | operation.extrusionStartedBlock = ^() { 50 | [weakSelf.progressIndicator setIndeterminate:YES]; 51 | weakSelf.statusLabel.stringValue = retract ? @"Retracting" : @"Extruding"; 52 | }; 53 | 54 | operation.extrusionStoppedBlock = ^() { 55 | [weakSelf operationDidStop]; 56 | }; 57 | 58 | [operation start]; 59 | } 60 | 61 | 62 | - (void)operationDidStop { 63 | self.operation = nil; 64 | self.statusLabel.stringValue = @""; 65 | [self.progressIndicator stopAnimation:nil]; 66 | self.progressIndicator.hidden = YES; 67 | 68 | [self.actionButtons enumerateObjectsUsingBlock:^(NSButton *button, NSUInteger index, BOOL *stop) { 69 | button.enabled = YES; 70 | button.title = self.actionButtonTitles[index]; 71 | button.keyEquivalent = @""; 72 | }]; 73 | self.closeButton.enabled = YES; 74 | } 75 | 76 | 77 | - (void)raise { 78 | __weak __typeof__(self) weakSelf = self; 79 | TFPRaiseHeadOperation *operation = [[TFPRaiseHeadOperation alloc] initWithPrinter:self.printer]; 80 | operation.targetHeight = 70; 81 | self.progressIndicator.hidden = NO; 82 | 83 | self.operation = operation; 84 | 85 | operation.didStartBlock = ^{ 86 | weakSelf.statusLabel.stringValue = @"Raising…"; 87 | [weakSelf.progressIndicator setIndeterminate:YES]; 88 | [weakSelf.progressIndicator startAnimation:nil]; 89 | }; 90 | 91 | operation.didStopBlock = ^(BOOL didMove){ 92 | [weakSelf operationDidStop]; 93 | }; 94 | 95 | weakSelf.statusLabel.stringValue = @"Starting…"; 96 | [operation start]; 97 | } 98 | 99 | 100 | - (void)viewDidLoad { 101 | [super viewDidLoad]; 102 | self.actionButtons = @[self.retractButton, 103 | self.extrudeButton, 104 | self.raiseButton, 105 | ]; 106 | self.actionButtonTitles = [self.actionButtons valueForKey:@"title"]; 107 | } 108 | 109 | 110 | - (void)viewDidAppear { 111 | [super viewDidAppear]; 112 | self.view.window.styleMask &= ~NSResizableWindowMask; 113 | } 114 | 115 | 116 | - (IBAction)buttonAction:(id)sender { 117 | if(self.operation) { 118 | [self.operation stop]; 119 | self.statusLabel.stringValue = @"Stopping…"; 120 | }else{ 121 | for(NSButton *button in self.actionButtons) { 122 | if(button != sender) { 123 | button.enabled = NO; 124 | }else{ 125 | button.title = @"Stop"; 126 | button.keyEquivalent = @"\r"; 127 | } 128 | } 129 | self.closeButton.enabled = NO; 130 | 131 | if(sender == self.retractButton) { 132 | [self startRetract:YES]; 133 | 134 | }else if(sender == self.extrudeButton) { 135 | [self startRetract:NO]; 136 | 137 | }else if(sender == self.raiseButton) { 138 | [self raise]; 139 | } 140 | } 141 | } 142 | 143 | 144 | @end -------------------------------------------------------------------------------- /MicroPrint UI/TFPPrintingProgressViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrintingProgressViewController.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Tue 2015-07-14. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | @class TFPGCodeProgram, TFPPrinter, TFPPrintParameters; 11 | 12 | @interface TFPPrintingProgressViewController : NSViewController 13 | @property TFPGCodeProgram *program; 14 | @property TFPPrinter *printer; 15 | @property TFPPrintParameters *printParameters; 16 | 17 | - (void)start; 18 | @property (copy) void(^endHandler)(BOOL didFinishPrint); 19 | 20 | - (NSString*)elapsedTimeString; 21 | @end -------------------------------------------------------------------------------- /MicroPrint UI/TFPScriptManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPScriptManager.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Thu 2015-07-23. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | @import AppKit; 10 | 11 | 12 | @interface TFPScriptManager : NSObject 13 | @property (readonly) NSArray *recentScripts; 14 | 15 | + (instancetype)sharedManager; 16 | 17 | - (void)addRecentScript:(NSURL*)URL; 18 | - (NSOpenPanel*)openPanelForSelectingScript; 19 | - (BOOL)runScriptFile:(NSURL*)URL printName:(NSString*)printName duration:(NSString*)durationString errorInfo:(NSDictionary**)error; 20 | @end -------------------------------------------------------------------------------- /MicroPrint UI/TFPScriptManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPScriptManager.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Thu 2015-07-23. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPScriptManager.h" 10 | #import "TFPExtras.h" 11 | @import AppKit; 12 | 13 | static const NSUInteger maxRecentURLCount = 10; 14 | 15 | 16 | @interface TFPScriptManager () 17 | @property (readwrite) NSArray *recentScripts; 18 | @end 19 | 20 | 21 | @implementation TFPScriptManager 22 | 23 | 24 | + (instancetype)sharedManager { 25 | static TFPScriptManager *singleton; 26 | return singleton ?: (singleton = [self new]); 27 | } 28 | 29 | 30 | - (void)readSavedRecentData { 31 | NSArray *bookmarks = [[NSUserDefaults standardUserDefaults] objectForKey:@"RecentScripts"] ?: @[]; 32 | 33 | self.recentScripts = [bookmarks tf_mapWithBlock:^NSURL*(NSData *bookmark) { 34 | return [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithoutUI | NSURLBookmarkResolutionWithoutMounting relativeToURL:nil bookmarkDataIsStale:nil error:nil]; 35 | }]; 36 | } 37 | 38 | 39 | - (void)writeRecentData { 40 | NSArray *bookmarks = [self.recentScripts tf_mapWithBlock:^NSData*(NSURL *URL) { 41 | return [URL bookmarkDataWithOptions:0 includingResourceValuesForKeys:nil relativeToURL:nil error:nil]; 42 | }]; 43 | 44 | [[NSUserDefaults standardUserDefaults] setObject:bookmarks forKey:@"RecentScripts"]; 45 | } 46 | 47 | 48 | - (instancetype)init { 49 | if(!(self = [super init])) return nil; 50 | 51 | [self readSavedRecentData]; 52 | 53 | return self; 54 | } 55 | 56 | 57 | - (void)addRecentScript:(NSURL*)URL { 58 | NSMutableArray *URLs = [self mutableArrayValueForKey:@"recentScripts"]; 59 | [URLs removeObject:URL]; 60 | [URLs insertObject:URL atIndex:0]; 61 | 62 | if(URLs.count > maxRecentURLCount) { 63 | [URLs removeObjectsInRange:NSMakeRange(maxRecentURLCount, URLs.count-maxRecentURLCount)]; 64 | } 65 | 66 | [self writeRecentData]; 67 | } 68 | 69 | 70 | - (NSOpenPanel*)openPanelForSelectingScript { 71 | NSOpenPanel *openPanel = [NSOpenPanel openPanel]; 72 | openPanel.allowedFileTypes = @[@"com.apple.applescript.​script", @"scpt"]; 73 | return openPanel; 74 | } 75 | 76 | 77 | - (BOOL)runScriptFile:(NSURL*)URL printName:(NSString*)printName duration:(NSString*)durationString errorInfo:(NSDictionary**)error { 78 | NSAppleScript *script = [[NSAppleScript alloc] initWithContentsOfURL:URL error:error]; 79 | if(!script) { 80 | return NO; 81 | } 82 | 83 | const FourCharCode kASAppleScriptSuite = 'ascr'; 84 | const FourCharCode kASSubroutineEvent = 'psbr'; 85 | const FourCharCode keyASSubroutineName = 'snam'; 86 | 87 | NSAppleEventDescriptor *event = [NSAppleEventDescriptor appleEventWithEventClass:kASAppleScriptSuite eventID:kASSubroutineEvent targetDescriptor:nil returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID]; 88 | 89 | [event setParamDescriptor:[NSAppleEventDescriptor descriptorWithString:@"printFinished"] forKeyword:keyASSubroutineName]; 90 | 91 | NSAppleEventDescriptor *arguments = [NSAppleEventDescriptor listDescriptor]; 92 | [arguments insertDescriptor:[NSAppleEventDescriptor descriptorWithString:printName] atIndex:1]; 93 | [arguments insertDescriptor:[NSAppleEventDescriptor descriptorWithString:durationString] atIndex:2]; 94 | [event setParamDescriptor:arguments forKeyword:keyDirectObject]; 95 | 96 | return [script executeAppleEvent:event error:error] != nil; 97 | } 98 | 99 | 100 | @end 101 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPUIExtras.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPUITFPExtras.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Tue 2015-07-14. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TFPPrinter.h" 11 | 12 | 13 | @interface TFPPrinter (UIExtras) 14 | @property (readonly) NSImage *printerImage; 15 | @end 16 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPUIExtras.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPUIExtras.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Tue 2015-07-14. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPUIExtras.h" 10 | #import "TFPOperation.h" 11 | #import "TFPExtras.h" 12 | @import AppKit; 13 | 14 | 15 | @implementation TFPPrinter (UIExtras) 16 | 17 | 18 | - (NSImage *)printerImage { 19 | static NSMutableDictionary *images; 20 | if(!images) { 21 | images = [NSMutableDictionary new]; 22 | } 23 | 24 | NSDictionary *colorMapping = @{ 25 | @(TFPPrinterColorBlack): [NSColor colorWithCalibratedWhite:0.245 alpha:1.000], 26 | @(TFPPrinterColorSilver): [NSColor colorWithCalibratedWhite:0.549 alpha:1.000], 27 | @(TFPPrinterColorLightBlue): [NSColor colorWithCalibratedRed:0.220 green:0.761 blue:0.918 alpha:1.000], 28 | @(TFPPrinterColorGreen): [NSColor colorWithCalibratedRed:0.400 green:0.906 blue:0.224 alpha:1.000], 29 | @(TFPPrinterColorOrange): [NSColor colorWithCalibratedRed:0.988 green:0.255 blue:0.149 alpha:1.000], 30 | @(TFPPrinterColorWhite): [NSColor colorWithCalibratedWhite:0.948 alpha:1.000], 31 | @(TFPPrinterColorGrape): [NSColor colorWithDeviceRed:0.441 green:0.299 blue:0.678 alpha:1.000], 32 | @(TFPPrinterColorOther): [NSColor redColor], 33 | }; 34 | 35 | NSImage *image = images[@(self.color)]; 36 | if(image) { 37 | return image; 38 | } 39 | 40 | image = [[NSImage imageNamed:@"Micro"] copy]; 41 | NSColor *color = colorMapping[@(self.color)]; 42 | 43 | [image lockFocus]; 44 | [color set]; 45 | NSRectFillUsingOperation((CGRect){CGPointZero, image.size}, NSCompositeSourceIn); 46 | [image unlockFocus]; 47 | 48 | images[@(self.color)] = image; 49 | return image; 50 | } 51 | 52 | 53 | + (NSSet *)keyPathsForValuesAffectingPrinterImage { 54 | return [NSSet setWithObject:@"color"]; 55 | } 56 | 57 | 58 | - (NSString*)activityString { 59 | if(self.currentOperation) { 60 | return self.currentOperation.activityDescription; 61 | 62 | }else if(self.pendingConnection) { 63 | return @"Connecting…"; 64 | 65 | }else{ 66 | return @"Idle"; 67 | } 68 | } 69 | 70 | 71 | + (NSSet *)keyPathsForValuesAffectingActivityString { 72 | return @[@"currentOperation.activityDescription", @"pendingConnection"].tf_set; 73 | } 74 | 75 | 76 | - (NSString*)displayName { 77 | return self.serialNumber ?: @"Printer"; 78 | } 79 | 80 | 81 | + (NSSet *)keyPathsForValuesAffectingDisplayName { 82 | return @[@"serialNumber"].tf_set; 83 | } 84 | 85 | 86 | @end -------------------------------------------------------------------------------- /MicroPrint UI/TFPVisualPrintProgressView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPVisualPrintProgressView.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sat 2015-08-08. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | @class TFPPrintStatusController, TFPPrintParameters; 11 | 12 | 13 | @interface TFPVisualPrintProgressView : NSView 14 | @property CGSize fullViewSize; 15 | 16 | - (void)configureWithPrintStatusController:(TFPPrintStatusController*)statusController parameters:(TFPPrintParameters*)printParameters; 17 | @end -------------------------------------------------------------------------------- /MicroPrint UI/TFPVisualPrintProgressView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPVisualPrintProgressView.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sat 2015-08-08. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPVisualPrintProgressView.h" 10 | #import "TFPPrintJob.h" 11 | #import "TFPPrintStatusController.h" 12 | 13 | 14 | @interface TFPVisualPrintProgressView () 15 | @property id bitmap; 16 | 17 | @property CALayer *drawLayer; 18 | @property CGAffineTransform drawTransform; 19 | @property CGFloat drawScale; 20 | @end 21 | 22 | 23 | 24 | @implementation TFPVisualPrintProgressView 25 | 26 | 27 | - (void)configureWithPrintStatusController:(TFPPrintStatusController*)statusController parameters:(TFPPrintParameters*)printParameters { 28 | __weak __typeof__(self) weakSelf = self; 29 | 30 | TFPCuboid boundingBox = printParameters.boundingBox; 31 | CGSize viewSize = self.fullViewSize; 32 | 33 | CGFloat drawScale = 2; 34 | self.bitmap = CFBridgingRelease(CGBitmapContextCreate(NULL, viewSize.width * drawScale, viewSize.height * drawScale, 8, (viewSize.width*drawScale)*4, [NSColorSpace deviceRGBColorSpace].CGColorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedLast)); 35 | 36 | self.drawLayer = [CALayer layer]; 37 | self.drawLayer.bounds = CGRectMake(0, 0, viewSize.width, viewSize.height); 38 | self.drawLayer.backgroundColor = [NSColor whiteColor].CGColor; 39 | self.drawLayer.anchorPoint = CGPointZero; 40 | self.drawLayer.actions = @{@"contents": [NSNull null]}; 41 | self.drawLayer.contentsScale = drawScale; 42 | [self.layer addSublayer:self.drawLayer]; 43 | 44 | CGFloat margin = 20; 45 | viewSize.width -= 2*margin; 46 | viewSize.height -= 2*margin; 47 | 48 | CGAffineTransform transform = CGAffineTransformIdentity; 49 | double xScale = viewSize.width / boundingBox.xSize; 50 | double yScale = viewSize.height / boundingBox.ySize; 51 | double scale = MIN(xScale, yScale); 52 | 53 | CGFloat xOffset = (viewSize.width - (scale*boundingBox.xSize)) / 2 + margin; 54 | CGFloat yOffset = (viewSize.height - (scale*boundingBox.ySize)) / 2 + margin; 55 | transform = CGAffineTransformTranslate(transform, xOffset, yOffset); 56 | transform = CGAffineTransformScale(transform, scale, scale); 57 | transform = CGAffineTransformTranslate(transform, -boundingBox.x, -boundingBox.y); 58 | self.drawScale = scale; 59 | self.drawTransform = transform; 60 | 61 | CGContextRef context = (__bridge CGContextRef)self.bitmap; 62 | CGContextSetLineCap(context, kCGLineCapRound); 63 | CGContextSetLineWidth(context, self.drawScale * 0.8); 64 | CGContextSetStrokeColorWithColor(context, [NSColor blackColor].CGColor); 65 | CGContextScaleCTM(context, drawScale, drawScale); 66 | 67 | 68 | __block double xAdjustment = 0; 69 | __block double yAdjustment = 0; 70 | 71 | statusController.willMoveHandler = ^(TFPAbsolutePosition from, TFPAbsolutePosition to, double feedRate, TFPGCode *code) { 72 | double distance = TFPAbsolutePositionDistance(from, to); 73 | 74 | if([code.comment hasPrefix:@"BACKLASH"]) { 75 | xAdjustment += from.x - to.x; 76 | yAdjustment += from.y - to.y; 77 | } 78 | 79 | CGAffineTransform transform = weakSelf.drawTransform; 80 | CGPoint fromPoint = CGPointApplyAffineTransform(CGPointMake(from.x + xAdjustment, from.y + yAdjustment), transform); 81 | CGPoint toPoint = CGPointApplyAffineTransform(CGPointMake(to.x + xAdjustment, to.y + yAdjustment), transform); 82 | 83 | /* 84 | double distance = sqrt(pow(to.x - from.x, 2) + pow(to.y - from.y, 2)); 85 | double calculatedSpeed = (6288.78 * (feedRate-830))/((feedRate-828.465) * (feedRate+79.5622)); 86 | NSTimeInterval estimatedDuration = distance / calculatedSpeed; 87 | estimatedDuration /= weakSelf.printer.speedMultiplier; 88 | */ 89 | 90 | if(to.e > from.e && distance > FLT_EPSILON) { 91 | CGMutablePathRef path = (CGMutablePathRef)CFAutorelease(CGPathCreateMutable()); 92 | CGPathMoveToPoint(path, NULL, fromPoint.x, fromPoint.y); 93 | CGPathAddLineToPoint(path, NULL, toPoint.x, toPoint.y); 94 | 95 | CGContextRef context = (__bridge CGContextRef)weakSelf.bitmap; 96 | 97 | CGContextAddPath(context, path); 98 | CGContextStrokePath(context); 99 | [weakSelf updateImage]; 100 | } 101 | }; 102 | 103 | statusController.layerChangeHandler = ^{ 104 | CGContextRef context = (__bridge CGContextRef)weakSelf.bitmap; 105 | CGRect entireRect = CGRectMake(0, 0, CGBitmapContextGetWidth(context), CGBitmapContextGetHeight(context)); 106 | CGImageRef image = (CGImageRef)CFAutorelease(CGBitmapContextCreateImage(context)); 107 | 108 | CGContextSaveGState(context); 109 | CGContextClearRect(context, entireRect); 110 | CGContextSetAlpha(context, 0.5); 111 | CGContextConcatCTM(context, CGAffineTransformInvert(CGContextGetCTM(context))); 112 | CGContextDrawImage(context, entireRect, image); 113 | CGContextRestoreGState(context); 114 | }; 115 | 116 | } 117 | 118 | 119 | - (void)setHidden:(BOOL)hidden { 120 | [super setHidden:hidden]; 121 | [self updateImage]; 122 | } 123 | 124 | 125 | - (void)updateImage { 126 | if(!self.hiddenOrHasHiddenAncestor && self.bitmap) { 127 | self.drawLayer.contents = CFBridgingRelease(CGBitmapContextCreateImage((CGContextRef)self.bitmap)); 128 | } 129 | } 130 | 131 | 132 | @end 133 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPZeroHeadViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPZeroHeadViewController.h 3 | // microprint 4 | // 5 | // Created by William Waggoner on 8/1/15. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TFPCalibrationViewController.h" 11 | #import "TFPPrinter.h" 12 | 13 | @interface TFPZeroHeadViewController : TFPCalibrationViewController 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /MicroPrint UI/TFPZeroHeadViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPZeroHeadViewController.m 3 | // microprint 4 | // 5 | // Created by William Waggoner on 8/1/15. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPZeroHeadViewController.h" 10 | #import "TFPZeroBedOperation.h" 11 | #import "TFPExtras.h" 12 | 13 | @interface TFPZeroHeadViewController () 14 | @property IBOutlet NSTextField* txtHelp; 15 | @property IBOutlet NSButton* startButton; 16 | @property IBOutlet NSProgressIndicator *progressIndicator; 17 | @property IBOutlet NSTextField *statusLabel; 18 | @property TFPZeroBedOperation* operation; 19 | @end 20 | 21 | @implementation TFPZeroHeadViewController 22 | 23 | 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | self.operation = nil; 27 | } 28 | 29 | 30 | - (void)start { 31 | __weak __typeof__(self) weakSelf = self; 32 | TFPZeroBedOperation *operation = [[TFPZeroBedOperation alloc] initWithPrinter:self.printer]; 33 | self.operation = operation; 34 | 35 | operation.progressFeedback = ^(NSString *msg){ 36 | weakSelf.statusLabel.stringValue = msg; 37 | }; 38 | 39 | operation.didStopBlock = ^(BOOL completed){ 40 | [weakSelf operationDidStop]; 41 | 42 | if(completed) { 43 | NSAlert *alert = [NSAlert new]; 44 | alert.messageText = @"Bed location calibration finished"; 45 | alert.informativeText = @"You should now run the Bed Level Calibration to make sure corner levels are correct."; 46 | [alert addButtonWithTitle:@"OK"]; 47 | 48 | [alert beginSheetModalForWindow:weakSelf.view.window completionHandler:^(NSModalResponse returnCode) { 49 | [weakSelf dismissController:nil]; 50 | }]; 51 | } 52 | }; 53 | 54 | [operation start]; 55 | } 56 | 57 | - (IBAction)buttonPressed:(id)sender { 58 | 59 | if(sender == self.startButton) { 60 | if(self.operation) { 61 | [self.operation stop]; 62 | }else{ 63 | self.statusLabel.hidden = NO; 64 | self.progressIndicator.hidden = NO; 65 | self.statusLabel.stringValue = @"Starting…"; 66 | [self.progressIndicator setIndeterminate:YES]; 67 | [self.progressIndicator startAnimation:nil]; 68 | self.startButton.title = @"Stop"; 69 | self.startButton.keyEquivalent = @"\r"; 70 | [self start]; 71 | } 72 | } 73 | } 74 | 75 | - (void)operationDidStop { 76 | self.operation = nil; 77 | self.statusLabel.stringValue = @""; 78 | [self.progressIndicator stopAnimation:nil]; 79 | self.statusLabel.hidden = YES; 80 | self.progressIndicator.hidden = YES; 81 | self.startButton.title = @"Start"; 82 | self.startButton.keyEquivalent = @""; 83 | } 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /MicroPrint UI/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MicroPrint UI 4 | // 5 | // Created by Tomas Franzén on Mon 2015-07-13. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # microprint 2 | #### Printing software for M3D Micro for OS X 3 | 4 | MicroPrint is a command-line program for Mac. It takes a G-code file that you've previously sliced in a slicer like Cura, pre-processes the code the same way M3D does it with bed level measurements, backlash compensation and feed rate translation, and finally feeds it to your printer. 5 | 6 | MicroPrint is currently in alpha stage (or like M3D would call it; "beta!!!"), so don't expect full polish. It's meant for advanced users for now, so you need to be familiar with the command line. Like always, your printer may break if my software does something weird. It very most likely won't, but don't blame me if it does. 7 | 8 | Besides printing, MicroPrint can also do a few other things like retract and extrude filament manually. It extrudes until you press Return instead of the stupid repeating question in M3D's UI. 9 | 10 | Usage examples: 11 | 12 | microprint print teapot.gcode 13 | microprint print MyPrecious0.4mmTestBorder.gcode --filament ABS 14 | microprint extrude --temperature 250 15 | microprint raise 16 | 17 | See more by invoking `microprint --help` 18 | 19 | Here's a good guide for how to use Cura to generate G-code: https://printm3d.com/forums/discussion/1691/guide-how-to-print-abs-out-of-the-box-using-cura 20 | 21 | #### Notes: 22 | * You need to quit the M3D spooler to stop it from hogging the serial port to allow MicroPrint to connect to the printer. 23 | * No graceful aborting of prints. If you ctrl-C the program, it leaves things like the heater and fan running. I hope to fix this soon, too. 24 | * Progress reporting is stupid and is based only on the number of processed G-code lines. 25 | * MicroPrint requires OS X 10.10. It may very well work with older versions of OS X, but I'm not maintaining such compatibility. 26 | 27 | Future ideas: 28 | * Good print time estimation, with both duration and completion time. 29 | * Interactive 0.4 mm border calibration that asks you for corner height measurements and adjusts offsets automatically. 30 | * G-code console for executing raw G-code, with optional feed rate translation 31 | 32 | ##### Simplify3d Setup 33 | 34 | To use Simplify3d effectively you will need to change the Process definition for the Micro3d printer. We suggest that you 35 | make the following changes then save the definition under a different name. 36 | 37 | 1. Edit the Process, usually "Process1" 38 | 1. You should have `M3D Micro` selected as the Profile 39 | 1. Select the `Scripts` tab 40 | 1. Under "Additional terminal commands" **DELETE** the following lines: 41 | * `{STRIP ";"}` 42 | * `{PREPEND ";other temp:210\n;ideal temp:210\n"}` 43 | 1. Click "Save as New" and enter a new name for this profile. `M3D Micro - Microprint` might be a good name. 44 | 45 | If this is successful then the resulting GCode will have the Simplify3d Profile and Layer indicators in it. 46 | Microprint should detect these and display the settings during print setup and the layer progress as the print proceeds. 47 | -------------------------------------------------------------------------------- /microprint/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/.DS_Store -------------------------------------------------------------------------------- /microprint/ORSSerialRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORSSerialRequest.h 3 | // ORSSerialPort 4 | // 5 | // Created by Andrew Madsen on 4/21/14. 6 | // Copyright (c) 2014 Andrew Madsen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // Keep older versions of the compiler happy 12 | #ifndef NS_ASSUME_NONNULL_BEGIN 13 | #define NS_ASSUME_NONNULL_BEGIN 14 | #define NS_ASSUME_NONNULL_END 15 | #define nullable 16 | #define nonnullable 17 | #define __nullable 18 | #endif 19 | 20 | typedef BOOL(^ORSSerialRequestResponseEvaluator)(NSData * __nullable inputData); 21 | 22 | NS_ASSUME_NONNULL_BEGIN 23 | 24 | /** 25 | * An ORSSerialRequest encapsulates a generic "request" command sent via the serial 26 | * port. 27 | * 28 | * An ORSSerialRequest includes data to be sent out via the serial port. 29 | * It also can contain a block which is used to evaluate received 30 | * data to determine if/when a valid response to the request has been received from 31 | * the device on the other end of the port. Arbitrary information can be 32 | * associated with the ORSSerialRequest via its userInfo property. 33 | */ 34 | @interface ORSSerialRequest : NSObject 35 | 36 | /** 37 | * Creates and initializes an ORSSerialRequest instance. 38 | * 39 | * @param dataToSend The data to be sent on the serial port. 40 | * @param userInfo An arbitrary userInfo object. 41 | * @param timeout The maximum amount of time in seconds to wait for a response. Pass -1.0 to wait indefinitely. 42 | * @param responseEvaluator A block used to evaluate whether received data constitutes a valid response to the request. 43 | * May be nil. If responseEvaluator is nil, the request is assumed not to require a response, and the next request in the queue will 44 | * be sent immediately. 45 | * 46 | * @return An initialized ORSSerialRequest instance. 47 | */ 48 | + (instancetype)requestWithDataToSend:(NSData *)dataToSend 49 | userInfo:(nullable id)userInfo 50 | timeoutInterval:(NSTimeInterval)timeout 51 | responseEvaluator:(nullable ORSSerialRequestResponseEvaluator)responseEvaluator; 52 | 53 | /** 54 | * Initializes an ORSSerialRequest instance. 55 | * 56 | * @param dataToSend The data to be sent on the serial port. 57 | * @param userInfo An arbitrary userInfo object. 58 | * @param timeout The maximum amount of time in seconds to wait for a response. Pass -1.0 to wait indefinitely. 59 | * @param responseEvaluator A block used to evaluate whether received data constitutes a valid response to the request. 60 | * May be nil. If responseEvaluator is nil, the request is assumed not to require a response, and the next request in the queue will 61 | * be sent immediately. 62 | * 63 | * @return An initialized ORSSerialRequest instance. 64 | */ 65 | - (instancetype)initWithDataToSend:(NSData *)dataToSend 66 | userInfo:(nullable id)userInfo 67 | timeoutInterval:(NSTimeInterval)timeout 68 | responseEvaluator:(nullable ORSSerialRequestResponseEvaluator)responseEvaluator; 69 | 70 | /** 71 | * Can be used to determine if a block of data is a valid response to the request encapsulated 72 | * by the receiver. If the receiver doesn't have a response data evaulator block, this method 73 | * always returns YES. 74 | * 75 | * @param responseData Data received from a serial port. 76 | * 77 | * @return YES if the data is a valid response, NO otherwise. 78 | */ 79 | - (BOOL)dataIsValidResponse:(nullable NSData *)responseData; 80 | 81 | /** 82 | * Data to be sent on the serial port when the receiver is sent. 83 | */ 84 | @property (nonatomic, strong, readonly) NSData *dataToSend; 85 | 86 | /** 87 | * Arbitrary object (e.g. NSDictionary) used to store additional data 88 | * about the request. 89 | */ 90 | @property (nonatomic, strong, readonly, nullable) id userInfo; 91 | 92 | /** 93 | * The maximum amount of time to wait for a response before timing out. 94 | * Negative values indicate that serial port will wait forever for a response 95 | * without timing out. 96 | */ 97 | @property (nonatomic, readonly) NSTimeInterval timeoutInterval; 98 | 99 | /** 100 | * Unique identifier for the request. 101 | */ 102 | @property (nonatomic, strong, readonly) NSString *UUIDString; 103 | 104 | @end 105 | 106 | NS_ASSUME_NONNULL_END -------------------------------------------------------------------------------- /microprint/ORSSerialRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORSSerialRequest.h 3 | // ORSSerialPort 4 | // 5 | // Created by Andrew Madsen on 4/21/14. 6 | // Copyright (c) 2014 Andrew Madsen. All rights reserved. 7 | // 8 | 9 | #import "ORSSerialRequest.h" 10 | 11 | @interface ORSSerialRequest () 12 | 13 | @property (nonatomic, strong, readwrite) NSData *dataToSend; 14 | @property (nonatomic, strong, readwrite) id userInfo; 15 | @property (nonatomic, readwrite) NSTimeInterval timeoutInterval; 16 | @property (nonatomic, strong) ORSSerialRequestResponseEvaluator responseEvaluator; 17 | @property (nonatomic, strong, readwrite) NSString *UUIDString; 18 | 19 | @end 20 | 21 | @implementation ORSSerialRequest 22 | 23 | + (instancetype)requestWithDataToSend:(NSData *)dataToSend 24 | userInfo:(id)userInfo 25 | timeoutInterval:(NSTimeInterval)timeout 26 | responseEvaluator:(ORSSerialRequestResponseEvaluator)responseEvaluator; 27 | { 28 | return [[self alloc] initWithDataToSend:dataToSend 29 | userInfo:userInfo 30 | timeoutInterval:timeout 31 | responseEvaluator:responseEvaluator]; 32 | } 33 | 34 | - (instancetype)initWithDataToSend:(NSData *)dataToSend 35 | userInfo:(id)userInfo 36 | timeoutInterval:(NSTimeInterval)timeout 37 | responseEvaluator:(ORSSerialRequestResponseEvaluator)responseEvaluator; 38 | { 39 | self = [super init]; 40 | if (self) { 41 | _dataToSend = dataToSend; 42 | _userInfo = userInfo; 43 | _timeoutInterval = timeout; 44 | _responseEvaluator = responseEvaluator; 45 | CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault); 46 | _UUIDString = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuid)); 47 | CFRelease(uuid); 48 | } 49 | return self; 50 | } 51 | 52 | - (NSString *)description 53 | { 54 | return [NSString stringWithFormat:@"%@ data: %@ userInfo: %@ timeout interval: %f", [super description], self.dataToSend, self.userInfo, self.timeoutInterval]; 55 | } 56 | 57 | - (BOOL)dataIsValidResponse:(NSData *)responseData 58 | { 59 | if (!self.responseEvaluator) return YES; 60 | 61 | return self.responseEvaluator(responseData); 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /microprint/ProfileTranslations.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1404 2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 Menlo-Regular;\f2\fnil\fcharset0 Menlo-Bold; 3 | } 4 | {\colortbl;\red255\green255\blue255;\red196\green26\blue22;} 5 | \margl1440\margr1440\vieww9000\viewh8400\viewkind0 6 | \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 7 | 8 | \f0\fs32 \cf0 Key name translations for slicers\ 9 | \ 10 | Keys we are interested in (original Cura names):\ 11 | \ 12 | \pard\tx577\pardeftab577\pardirnatural\partightenfactor0 13 | 14 | \f1\fs24 \cf2 \CocoaLigature0 layer_height\ 15 | wall_thickness\ 16 | print_speed\ 17 | fill_density\ 18 | support\ 19 | platform_adhesion\ 20 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\partightenfactor0 21 | \cf0 \CocoaLigature1 \ 22 | * Slic3r names for the above:\ 23 | \ 24 | layer_height\ 25 | perimeters * "external perimeters extrusion width"\ 26 | perimeter_speed\ 27 | fill_density\ 28 | support_material (1/0:YES/NO)\ 29 | raft_layers > 0 = RAFT(n)/brim_width > 0 = BRIM(n)\ 30 | \ 31 | * Simplify3d names\ 32 | \ 33 | \ 34 | \ 35 | * Table\ 36 | \pard\tx2879\pardirnatural\partightenfactor0 37 | 38 | \f2\b \cf0 Original 39 | \f1\b0 40 | \f2\b Slic3r2 41 | \f1\b0 \ 42 | \pard\tx2888\pardirnatural\partightenfactor0 43 | \cf0 \ 44 | \pard\tx2876\tx5761\pardeftab577\pardirnatural\partightenfactor0 45 | \cf2 \CocoaLigature0 layer_height \cf0 \CocoaLigature1 layer_height\cf2 \CocoaLigature0 \ 46 | \pard\tx2884\pardeftab577\pardirnatural\partightenfactor0 47 | \cf2 wall_thickness \cf0 \CocoaLigature1 perimeters * "external perimeters extrusion width"\cf2 \CocoaLigature0 \ 48 | \pard\tx2877\pardeftab577\pardirnatural\partightenfactor0 49 | \cf2 print_speed \cf0 \CocoaLigature1 perimeter_speed\cf2 \CocoaLigature0 \ 50 | \pard\tx2857\pardeftab577\pardirnatural\partightenfactor0 51 | \cf2 fill_density \cf0 \CocoaLigature1 fill_density\cf2 \CocoaLigature0 \ 52 | \pard\tx2884\pardeftab577\pardirnatural\partightenfactor0 53 | \cf2 support \cf0 \CocoaLigature1 support_material (1/0:YES/NO)\cf2 \CocoaLigature0 \ 54 | \pard\tx2876\pardeftab577\pardirnatural\partightenfactor0 55 | \cf2 platform_adhesion \cf0 \CocoaLigature1 raft_layers > 0 = RAFT(n)/brim_width > 0 = BRIM(n)\cf2 \CocoaLigature0 \ 56 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab577\pardirnatural\partightenfactor0 57 | \cf0 \CocoaLigature1 \ 58 | } -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Modules: -------------------------------------------------------------------------------- 1 | Versions/Current/Modules -------------------------------------------------------------------------------- /microprint/Sparkle.framework/PrivateHeaders: -------------------------------------------------------------------------------- 1 | Versions/Current/PrivateHeaders -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Resources: -------------------------------------------------------------------------------- 1 | Versions/Current/Resources -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Sparkle: -------------------------------------------------------------------------------- 1 | Versions/Current/Sparkle -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Headers/SUAppcast.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUAppcast.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 3/12/06. 6 | // Copyright 2006 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SUAPPCAST_H 10 | #define SUAPPCAST_H 11 | 12 | #import 13 | #import "SUExport.h" 14 | 15 | @class SUAppcastItem; 16 | SU_EXPORT @interface SUAppcast : NSObject 17 | 18 | @property (copy) NSString *userAgentString; 19 | @property (copy) NSDictionary *httpHeaders; 20 | 21 | - (void)fetchAppcastFromURL:(NSURL *)url completionBlock:(void (^)(NSError *))err; 22 | 23 | @property (readonly, copy) NSArray *items; 24 | @end 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Headers/SUAppcastItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUAppcastItem.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 3/12/06. 6 | // Copyright 2006 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SUAPPCASTITEM_H 10 | #define SUAPPCASTITEM_H 11 | 12 | #include "SUExport.h" 13 | 14 | SU_EXPORT @interface SUAppcastItem : NSObject 15 | @property (copy, readonly) NSString *title; 16 | @property (copy, readonly) NSDate *date; 17 | @property (copy, readonly) NSString *itemDescription; 18 | @property (strong, readonly) NSURL *releaseNotesURL; 19 | @property (copy, readonly) NSString *DSASignature; 20 | @property (copy, readonly) NSString *minimumSystemVersion; 21 | @property (copy, readonly) NSString *maximumSystemVersion; 22 | @property (strong, readonly) NSURL *fileURL; 23 | @property (copy, readonly) NSString *versionString; 24 | @property (copy, readonly) NSString *displayVersionString; 25 | @property (copy, readonly) NSDictionary *deltaUpdates; 26 | @property (strong, readonly) NSURL *infoURL; 27 | 28 | // Initializes with data from a dictionary provided by the RSS class. 29 | - (instancetype)initWithDictionary:(NSDictionary *)dict; 30 | - (instancetype)initWithDictionary:(NSDictionary *)dict failureReason:(NSString **)error; 31 | 32 | @property (getter=isDeltaUpdate, readonly) BOOL deltaUpdate; 33 | @property (getter=isCriticalUpdate, readonly) BOOL criticalUpdate; 34 | 35 | // Returns the dictionary provided in initWithDictionary; this might be useful later for extensions. 36 | @property (readonly, copy) NSDictionary *propertiesDictionary; 37 | 38 | - (NSURL *)infoURL; 39 | 40 | @end 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Headers/SUErrors.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUErrors.h 3 | // Sparkle 4 | // 5 | // Created by C.W. Betts on 10/13/14. 6 | // Copyright (c) 2014 Sparkle Project. All rights reserved. 7 | // 8 | 9 | #ifndef SUERRORS_H 10 | #define SUERRORS_H 11 | 12 | #import 13 | #import "SUExport.h" 14 | 15 | /** 16 | * Error domain used by Sparkle 17 | */ 18 | SU_EXPORT extern NSString *const SUSparkleErrorDomain; 19 | 20 | typedef NS_ENUM(OSStatus, SUError) { 21 | // Appcast phase errors. 22 | SUAppcastParseError = 1000, 23 | SUNoUpdateError = 1001, 24 | SUAppcastError = 1002, 25 | SURunningFromDiskImageError = 1003, 26 | 27 | // Downlaod phase errors. 28 | SUTemporaryDirectoryError = 2000, 29 | 30 | // Extraction phase errors. 31 | SUUnarchivingError = 3000, 32 | SUSignatureError = 3001, 33 | 34 | // Installation phase errors. 35 | SUFileCopyFailure = 4000, 36 | SUAuthenticationFailure = 4001, 37 | SUMissingUpdateError = 4002, 38 | SUMissingInstallerToolError = 4003, 39 | SURelaunchError = 4004, 40 | SUInstallationError = 4005, 41 | SUDowngradeError = 4006 42 | }; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Headers/SUExport.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUExport.h 3 | // Sparkle 4 | // 5 | // Created by Jake Petroules on 2014-08-23. 6 | // Copyright (c) 2014 Sparkle Project. All rights reserved. 7 | // 8 | 9 | #ifndef SUEXPORT_H 10 | #define SUEXPORT_H 11 | 12 | #ifdef BUILDING_SPARKLE 13 | #define SU_EXPORT __attribute__((visibility("default"))) 14 | #else 15 | #define SU_EXPORT 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Headers/SUStandardVersionComparator.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUStandardVersionComparator.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 12/21/07. 6 | // Copyright 2007 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SUSTANDARDVERSIONCOMPARATOR_H 10 | #define SUSTANDARDVERSIONCOMPARATOR_H 11 | 12 | #import "SUExport.h" 13 | #import "SUVersionComparisonProtocol.h" 14 | 15 | /*! 16 | Sparkle's default version comparator. 17 | 18 | This comparator is adapted from MacPAD, by Kevin Ballard. 19 | It's "dumb" in that it does essentially string comparison, 20 | in components split by character type. 21 | */ 22 | SU_EXPORT @interface SUStandardVersionComparator : NSObject 23 | 24 | /*! 25 | Returns a singleton instance of the comparator. 26 | */ 27 | + (SUStandardVersionComparator *)defaultComparator; 28 | 29 | /*! 30 | Compares version strings through textual analysis. 31 | 32 | See the implementation for more details. 33 | */ 34 | - (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB; 35 | @end 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUVersionComparisonProtocol.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 12/21/07. 6 | // Copyright 2007 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SUVERSIONCOMPARISONPROTOCOL_H 10 | #define SUVERSIONCOMPARISONPROTOCOL_H 11 | 12 | #import 13 | #import "SUExport.h" 14 | 15 | /*! 16 | Provides version comparison facilities for Sparkle. 17 | */ 18 | @protocol SUVersionComparison 19 | 20 | /*! 21 | An abstract method to compare two version strings. 22 | 23 | Should return NSOrderedAscending if b > a, NSOrderedDescending if b < a, 24 | and NSOrderedSame if they are equivalent. 25 | */ 26 | - (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB; // *** MAY BE CALLED ON NON-MAIN THREAD! 27 | 28 | @end 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Headers/SUVersionDisplayProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUVersionDisplayProtocol.h 3 | // EyeTV 4 | // 5 | // Created by Uli Kusterer on 08.12.09. 6 | // Copyright 2009 Elgato Systems GmbH. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SUExport.h" 11 | 12 | /*! 13 | Applies special display formatting to version numbers. 14 | */ 15 | @protocol SUVersionDisplay 16 | 17 | /*! 18 | Formats two version strings. 19 | 20 | Both versions are provided so that important distinguishing information 21 | can be displayed while also leaving out unnecessary/confusing parts. 22 | */ 23 | - (void)formatVersion:(NSString **)inOutVersionA andVersion:(NSString **)inOutVersionB; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Headers/Sparkle.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sparkle.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 3/16/06. (Modified by CDHW on 23/12/07) 6 | // Copyright 2006 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SPARKLE_H 10 | #define SPARKLE_H 11 | 12 | // This list should include the shared headers. It doesn't matter if some of them aren't shared (unless 13 | // there are name-space collisions) so we can list all of them to start with: 14 | 15 | #import 16 | #import 17 | #import 18 | #import 19 | #import 20 | #import 21 | #import 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module Sparkle { 2 | umbrella header "Sparkle.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/PrivateHeaders/SUUnarchiver.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUUnarchiver.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 3/16/06. 6 | // Copyright 2006 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SUUNARCHIVER_H 10 | #define SUUNARCHIVER_H 11 | 12 | @class SUHost; 13 | @protocol SUUnarchiverDelegate; 14 | 15 | @interface SUUnarchiver : NSObject 16 | 17 | @property (copy, readonly) NSString *archivePath; 18 | @property (weak, readonly) NSString *updateHostBundlePath; 19 | @property (weak) id delegate; 20 | 21 | + (SUUnarchiver *)unarchiverForPath:(NSString *)path updatingHostBundlePath:(NSString *)host; 22 | 23 | - (void)start; 24 | @end 25 | 26 | @protocol SUUnarchiverDelegate 27 | - (void)unarchiverDidFinish:(SUUnarchiver *)unarchiver; 28 | - (void)unarchiverDidFail:(SUUnarchiver *)unarchiver; 29 | @optional 30 | - (void)unarchiver:(SUUnarchiver *)unarchiver extractedProgress:(double)progress; 31 | @end 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 14E7f 7 | CFBundleDevelopmentRegion 8 | English 9 | CFBundleExecutable 10 | Autoupdate 11 | CFBundleIconFile 12 | AppIcon 13 | CFBundleIdentifier 14 | org.sparkle-project.Sparkle.Autoupdate 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.10.0 git-9646b0b 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.10.0 25 | DTCompiler 26 | com.apple.compilers.llvm.clang.1_0 27 | DTPlatformBuild 28 | 6D1002 29 | DTPlatformVersion 30 | GM 31 | DTSDKBuild 32 | 14D125 33 | DTSDKName 34 | macosx10.10 35 | DTXcode 36 | 0631 37 | DTXcodeBuild 38 | 6D1002 39 | LSBackgroundOnly 40 | 1 41 | LSMinimumSystemVersion 42 | 10.7 43 | LSUIElement 44 | 1 45 | NSMainNibFile 46 | MainMenu 47 | NSPrincipalClass 48 | NSApplication 49 | 50 | 51 | -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/MacOS/Autoupdate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/MacOS/Autoupdate -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/AppIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/AppIcon.icns -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/SUStatus.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/SUStatus.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ar.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ar.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/cs.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/cs.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/da.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/da.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/de.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/de.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/el.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/el.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/en.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/en.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/es.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/es.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/fr.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/fr.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/is.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/is.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/it.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/it.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ja.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ja.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ko.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ko.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/nb.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/nb.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/nl.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/nl.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pl.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pl.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pt_BR.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pt_BR.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pt_PT.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/pt_PT.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ro.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ro.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ru.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/ru.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sk.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sk.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sl.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sl.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sv.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/sv.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/th.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/th.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/tr.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/tr.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/uk.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/uk.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/zh_CN.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/zh_CN.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/zh_TW.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Resources/zh_TW.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 14E7f 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | Sparkle 11 | CFBundleIdentifier 12 | org.andymatuschak.Sparkle 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | Sparkle 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.10.0 git-9646b0b 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.10.0rc1 25 | DTCompiler 26 | com.apple.compilers.llvm.clang.1_0 27 | DTPlatformBuild 28 | 6D1002 29 | DTPlatformVersion 30 | GM 31 | DTSDKBuild 32 | 14D125 33 | DTSDKName 34 | macosx10.10 35 | DTXcode 36 | 0631 37 | DTXcodeBuild 38 | 6D1002 39 | SUAppendVersionNumber 40 | 1 41 | SUEnableAutomatedDowngrades 42 | 0 43 | SUNormalizeInstalledApplicationName 44 | 0 45 | SURelaunchToolName 46 | Autoupdate 47 | 48 | 49 | -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/SUStatus.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/SUStatus.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ar.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ar.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ar.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ar.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/cs.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/cs.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/cs.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/cs.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/da.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/da.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/da.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/da.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/de.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/de.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/el.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/el.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/el.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/el.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/el.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/el.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/el.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/el.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/es.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/es.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/fr.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/fr.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/fr_CA.lproj: -------------------------------------------------------------------------------- 1 | fr.lproj -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/is.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/is.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/is.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/is.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/it.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/it.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ja.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ja.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ja.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ja.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ko.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ko.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ko.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ko.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/nb.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/nb.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/nb.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/nb.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/nb.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/nb.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/nb.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/nb.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/nl.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/nl.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/pl.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/pl.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/pl.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/pl.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/pt.lproj: -------------------------------------------------------------------------------- 1 | pt_BR.lproj -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ro.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ro.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ro.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ro.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/ru.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/ru.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/sk.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/sk.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/sk.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/sk.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/sl.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/sl.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/sl.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/sl.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/sv.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/sv.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/th.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/th.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/th.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/th.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/tr.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/tr.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/tr.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/tr.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/uk.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/uk.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/uk.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/uk.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUAutomaticUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUAutomaticUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdateAlert.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdateAlert.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdatePermissionPrompt.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdatePermissionPrompt.nib -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/Sparkle.strings -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/A/Sparkle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomasf/microprint/e645933e7c9887de43ab698e6bddd637af4695a5/microprint/Sparkle.framework/Versions/A/Sparkle -------------------------------------------------------------------------------- /microprint/Sparkle.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /microprint/TFAsyncOperationCoalescer.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFAsyncOperationCoalescer.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sun 2015-08-09. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TFAsyncOperationCoalescer : NSObject 12 | @property (copy) void(^completionBlock)(); 13 | @property (copy) void(^progressUpdateBlock)(double progress); 14 | 15 | - (void(^)(double progress))addOperation; 16 | @end 17 | -------------------------------------------------------------------------------- /microprint/TFAsyncOperationCoalescer.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFAsyncOperationCoalescer.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sun 2015-08-09. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFAsyncOperationCoalescer.h" 10 | 11 | @interface TFAsyncOperationCoalescer () 12 | @property NSMutableDictionary *operationProgress; 13 | @property NSUInteger operationCount; 14 | @end 15 | 16 | 17 | @implementation TFAsyncOperationCoalescer 18 | 19 | 20 | - (instancetype)init { 21 | if(!(self = [super init])) return nil; 22 | 23 | self.operationProgress = [NSMutableDictionary new]; 24 | 25 | return self; 26 | } 27 | 28 | 29 | - (void)updateProgress { 30 | double sum = 0; 31 | BOOL anyIncomplete = NO; 32 | for(NSNumber *ID in self.operationProgress) { 33 | double value = [self.operationProgress[ID] doubleValue]; 34 | if(value < 1) { 35 | anyIncomplete = YES; 36 | } 37 | sum += value; 38 | } 39 | 40 | if(!anyIncomplete) { 41 | self.completionBlock(); 42 | }else{ 43 | if(self.progressUpdateBlock) { 44 | self.progressUpdateBlock(sum / self.operationProgress.count); 45 | } 46 | } 47 | } 48 | 49 | 50 | - (void(^)(double progress))addOperation { 51 | NSUInteger ID = self.operationCount++; 52 | self.operationProgress[@(ID)] = @0; 53 | 54 | return ^(double progress){ 55 | if(progress >= 1) { 56 | self.operationProgress[@(ID)] = @1; 57 | }else{ 58 | self.operationProgress[@(ID)] = @(progress); 59 | } 60 | [self updateProgress]; 61 | }; 62 | } 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /microprint/TFDataBuilder.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFDataBuilder.h 3 | // MicroPrint 4 | // 5 | // Created by Tomas Franzén on Mon 2015-06-22. 6 | // 7 | 8 | #import 9 | 10 | 11 | typedef NS_ENUM(NSUInteger, TFDataBuilderByteOrder) { 12 | TFDataBuilderByteOrderBigEndian, 13 | TFDataBuilderByteOrderLittleEndian, 14 | }; 15 | 16 | 17 | @interface TFDataBuilder : NSObject 18 | - (instancetype)initWithData:(NSData*)existingData; 19 | 20 | @property TFDataBuilderByteOrder byteOrder; 21 | 22 | - (void)appendData:(NSData*)data; 23 | - (void)appendBytes:(const void *)bytes length:(NSUInteger)length; 24 | - (void)appendString:(NSString*)string; // UTF-8 25 | - (void)appendString:(NSString*)string encoding:(NSStringEncoding)encoding; 26 | 27 | - (void)appendByte:(uint8_t)byte; 28 | - (void)appendInt16:(uint16_t)int16; 29 | - (void)appendInt32:(uint32_t)int32; 30 | - (void)appendInt64:(uint64_t)int64; 31 | 32 | - (void)appendFloat:(float)value; 33 | - (void)appendDouble:(double)value; 34 | 35 | @property (readonly) NSMutableData *data; 36 | @end 37 | -------------------------------------------------------------------------------- /microprint/TFDataBuilder.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFDataBuilder.m 3 | // MicroPrint 4 | // 5 | // Created by Tomas Franzén on Mon 2015-06-22. 6 | // 7 | 8 | #import "TFDataBuilder.h" 9 | 10 | @interface TFDataBuilder () 11 | @property (readwrite) NSMutableData *data; 12 | @end 13 | 14 | 15 | @implementation TFDataBuilder 16 | 17 | 18 | - (instancetype)initWithData:(NSData*)existingData { 19 | if(!(self = [super init])) return nil; 20 | 21 | self.data = [existingData mutableCopy] ?: [NSMutableData new]; 22 | 23 | return self; 24 | } 25 | 26 | 27 | - (instancetype)init { 28 | return [self initWithData:[NSData data]]; 29 | } 30 | 31 | 32 | - (void)appendData:(NSData*)data { 33 | [self.data appendData:data]; 34 | } 35 | 36 | 37 | - (void)appendString:(NSString*)string { 38 | [self appendString:string encoding:NSUTF8StringEncoding]; 39 | } 40 | 41 | 42 | - (void)appendBytes:(const void *)bytes length:(NSUInteger)length { 43 | [self.data appendBytes:bytes length:length]; 44 | } 45 | 46 | 47 | - (void)appendString:(NSString*)string encoding:(NSStringEncoding)encoding { 48 | [self appendData:[string dataUsingEncoding:encoding]]; 49 | } 50 | 51 | 52 | - (void)appendByte:(uint8_t)byte { 53 | [self.data appendBytes:&byte length:sizeof(byte)]; 54 | } 55 | 56 | 57 | - (void)appendInt16:(uint16_t)integer { 58 | if(self.byteOrder == TFDataBuilderByteOrderLittleEndian) { 59 | integer = NSSwapHostShortToLittle(integer); 60 | }else{ 61 | integer = NSSwapHostShortToBig(integer); 62 | } 63 | [self.data appendBytes:&integer length:sizeof(integer)]; 64 | } 65 | 66 | 67 | - (void)appendInt32:(uint32_t)integer { 68 | if(self.byteOrder == TFDataBuilderByteOrderLittleEndian) { 69 | integer = NSSwapHostIntToLittle(integer); 70 | }else{ 71 | integer = NSSwapHostIntToBig(integer); 72 | } 73 | [self.data appendBytes:&integer length:sizeof(integer)]; 74 | } 75 | 76 | 77 | - (void)appendInt64:(uint64_t)integer { 78 | if(self.byteOrder == TFDataBuilderByteOrderLittleEndian) { 79 | integer = NSSwapHostLongLongToLittle(integer); 80 | }else{ 81 | integer = NSSwapHostLongLongToBig(integer); 82 | } 83 | [self.data appendBytes:&integer length:sizeof(integer)]; 84 | } 85 | 86 | 87 | - (void)appendFloat:(float)value { 88 | NSSwappedFloat swapped; 89 | if(self.byteOrder == TFDataBuilderByteOrderLittleEndian) { 90 | swapped = NSSwapHostFloatToLittle(value); 91 | }else{ 92 | swapped = NSSwapHostFloatToBig(value); 93 | } 94 | [self.data appendBytes:&swapped length:sizeof(swapped)]; 95 | } 96 | 97 | 98 | - (void)appendDouble:(double)value { 99 | NSSwappedDouble swapped; 100 | if(self.byteOrder == TFDataBuilderByteOrderLittleEndian) { 101 | swapped = NSSwapHostDoubleToLittle(value); 102 | }else{ 103 | swapped = NSSwapHostDoubleToBig(value); 104 | } 105 | [self.data appendBytes:&swapped length:sizeof(swapped)]; 106 | } 107 | 108 | 109 | @end -------------------------------------------------------------------------------- /microprint/TFP3DVector.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFDecimal3DPoint.h 3 | // MicroPrint 4 | // 5 | // 6 | 7 | #import 8 | #import "TFPGCodeHelpers.h" 9 | 10 | @interface TFP3DVector : NSObject 11 | + (instancetype)vectorWithX:(NSNumber*)x Y:(NSNumber*)Y Z:(NSNumber*)Z; 12 | 13 | + (instancetype)xyVectorWithX:(double)x y:(double)y; 14 | + (instancetype)zVector:(double)z; 15 | + (instancetype)xVector:(double)x; 16 | + (instancetype)yVector:(double)y; 17 | 18 | + (instancetype)zeroVector; 19 | + (instancetype)emptyVector; 20 | 21 | + (instancetype)vectorWithPosition:(TFPAbsolutePosition)position; 22 | 23 | @property (readonly) NSNumber *x; 24 | @property (readonly) NSNumber *y; 25 | @property (readonly) NSNumber *z; 26 | 27 | - (double)distanceToPoint:(TFP3DVector*)point; 28 | - (TFP3DVector*)vectorByDefaultingToValues:(TFP3DVector*)defaults; 29 | - (TFP3DVector*)vectorWithFieldsPresentInVector:(TFP3DVector*)otherVector; 30 | 31 | - (TFP3DVector*)vectorBySettingX:(double)x; 32 | - (TFP3DVector*)vectorBySettingY:(double)y; 33 | - (TFP3DVector*)vectorBySettingZ:(double)z; 34 | - (TFP3DVector*)vectorBySettingY:(double)y z:(double)z; 35 | - (TFP3DVector*)vectorByAdjustingZ:(double)delta; 36 | 37 | - (TFP3DVector*)absoluteVector; 38 | 39 | - (TFP3DVector*)vectorByAdding:(TFP3DVector*)vector; 40 | - (TFP3DVector*)vectorBySubtracting:(TFP3DVector*)vector; 41 | - (TFP3DVector*)vectorByDividingBy:(TFP3DVector*)vector; 42 | - (TFP3DVector*)vectorByMultiplyingBy:(TFP3DVector*)vector; 43 | 44 | - (TFP3DVector*)vectorByDividingByScalar:(double)value; 45 | - (TFP3DVector*)vectorByMultiplyingByScalar:(double)value; 46 | @end -------------------------------------------------------------------------------- /microprint/TFPApplicationDebug.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPApplicationDelegate+TFPApplicationDebug.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Mon 2015-08-31. 6 | // Copyright © 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPApplicationDelegate.h" 10 | 11 | @interface TFPApplicationDelegate (TFPApplicationDebug) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /microprint/TFPBedLevelCalibration.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPManualBedLevelCalibration.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sun 2015-07-12. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPOperation.h" 10 | 11 | typedef NS_ENUM(NSUInteger, TFPBedLevelCalibrationCorner) { 12 | TFPBedLevelCalibrationCornerCenter, 13 | TFPBedLevelCalibrationCornerBackLeft, 14 | TFPBedLevelCalibrationCornerBackRight, 15 | TFPBedLevelCalibrationCornerBackFrontRight, 16 | TFPBedLevelCalibrationCornerBackFrontLeft, 17 | 18 | TFPBedLevelCalibrationCornerLast = TFPBedLevelCalibrationCornerBackFrontLeft, 19 | }; 20 | 21 | 22 | @interface TFPBedLevelCalibration : TFPOperation 23 | - (BOOL)startAtLevel:(double)startZ heightTarget:(double)heightTarget; 24 | 25 | - (void)adjustUp; 26 | - (void)adjustDown; 27 | @property (readonly) double currentLevel; 28 | 29 | - (void)continue; 30 | 31 | @property (copy) void(^didStartMovingHandler)(); 32 | @property (copy) void(^didStopAtCornerHandler)(TFPBedLevelCalibrationCorner corner); 33 | @property (copy) void(^didFinishHandler)(); 34 | @end -------------------------------------------------------------------------------- /microprint/TFPBedLevelCompensator.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPBedLevelCompensator.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Thu 2015-08-20. 6 | // Copyright © 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TFPPrintParameters.h" 11 | 12 | 13 | @interface TFPBedLevelCompensator : NSObject 14 | - (instancetype)initWithBedLevel:(TFPBedLevelOffsets)level; 15 | 16 | - (double)zAdjustmentAtX:(double)x Y:(double)y; 17 | @end -------------------------------------------------------------------------------- /microprint/TFPDryRunPrinter.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPDryRunPrinter.h 3 | // MicroPrint 4 | // 5 | // Created by Tomas Franzén on Wed 2015-06-24. 6 | // 7 | 8 | #import "TFPPrinter.h" 9 | 10 | @interface TFPDryRunPrinter : TFPPrinter 11 | 12 | + (void)setSpeedMultiplier:(double)multiplier; 13 | @end 14 | -------------------------------------------------------------------------------- /microprint/TFPDryRunPrinter.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPDryRunPrinter.m 3 | // MicroPrint 4 | // 5 | // Created by Tomas Franzén on Wed 2015-06-24. 6 | // 7 | 8 | #import "TFPDryRunPrinter.h" 9 | #import "TFPExtras.h" 10 | #import "TFP3DVector.h" 11 | 12 | static double speedMultiplier = 10; 13 | 14 | 15 | @interface TFPPrinter (Private) 16 | @property (readwrite) BOOL pendingConnection; 17 | @property (readwrite) NSString *serialNumber; 18 | @end 19 | 20 | 21 | @interface TFPDryRunPrinter () 22 | @property TFP3DVector *simulatedPosition; 23 | @property double feedRate; 24 | @property BOOL relativeMode; 25 | @end 26 | 27 | 28 | @interface TFPPrinter (HelpersPrivate) 29 | - (void)fetchBedOffsetsWithCompletionHandler:(void(^)(BOOL success, TFPBedLevelOffsets offsets))completionHandler; 30 | - (void)setBedOffsets:(TFPBedLevelOffsets)offsets completionHandler:(void(^)(BOOL success))completionHandler; 31 | @end 32 | 33 | 34 | 35 | 36 | @implementation TFPDryRunPrinter 37 | 38 | 39 | - (instancetype)init { 40 | if(!(self = [super init])) return nil; 41 | 42 | self.simulatedPosition = [TFP3DVector zeroVector]; 43 | 44 | return self; 45 | } 46 | 47 | 48 | - (void)sendGCode:(TFPGCode*)code responseHandler:(void(^)(BOOL success, NSDictionary *value))block responseQueue:(dispatch_queue_t)queue { 49 | NSInteger G = [code valueForField:'G' fallback:-1]; 50 | NSTimeInterval duration = 0.02; 51 | 52 | if(G == 0 || G == 1) { 53 | TFP3DVector *movement = [[code movementVector] vectorByDefaultingToValues:self.simulatedPosition]; 54 | self.feedRate = [code valueForField:'F' fallback:self.feedRate]; 55 | 56 | if(self.relativeMode) { 57 | movement = [TFP3DVector vectorWithX:@(self.simulatedPosition.x.doubleValue + movement.x.doubleValue) 58 | Y:@(self.simulatedPosition.y.doubleValue + movement.y.doubleValue) 59 | Z:@(self.simulatedPosition.z.doubleValue + movement.z.doubleValue)]; 60 | } 61 | 62 | double distance = [self.simulatedPosition distanceToPoint:movement]; 63 | 64 | double calculatedSpeed = (6288.78 * (self.feedRate-830))/((self.feedRate-828.465) * (self.feedRate+79.5622)); 65 | duration = distance / calculatedSpeed; 66 | duration /= self.speedMultiplier; 67 | self.simulatedPosition = movement; 68 | 69 | } else if(G == 90) { 70 | self.relativeMode = NO; 71 | 72 | } else if(G == 91) { 73 | self.relativeMode = YES; 74 | 75 | } else if(G == 30 || G == 28) { 76 | TFP3DVector *movement = [TFP3DVector vectorWithX:@50 Y:@50 Z:(G == 30 ? @0 : self.simulatedPosition.z)]; 77 | self.feedRate = [code valueForField:'F' fallback:self.feedRate]; 78 | 79 | double distance = [self.simulatedPosition distanceToPoint:movement]; 80 | 81 | double calculatedSpeed = (6288.78 * (self.feedRate-830))/((self.feedRate-828.465) * (self.feedRate+79.5622)); 82 | duration = distance / calculatedSpeed; 83 | duration = (duration / self.speedMultiplier) + 4; // At least 4 seconds 84 | self.simulatedPosition = movement; 85 | } 86 | 87 | dispatch_after(dispatch_time(0, duration * NSEC_PER_SEC), queue, ^{ 88 | if(block) { 89 | block(YES, @{}); 90 | } 91 | }); 92 | } 93 | 94 | 95 | - (TFPPrinterColor)color { 96 | return TFPPrinterColorOther; 97 | } 98 | 99 | 100 | - (NSString *)firmwareVersion { 101 | return @"0000000000"; 102 | } 103 | 104 | 105 | - (void)fetchBacklashValuesWithCompletionHandler:(void(^)(BOOL success, TFPBacklashValues values))completionHandler { 106 | dispatch_after(dispatch_time(0, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 107 | completionHandler(YES, (TFPBacklashValues){0.33, 0.69, 1500}); 108 | }); 109 | } 110 | 111 | 112 | - (void)fetchBedOffsetsWithCompletionHandler:(void (^)(BOOL, TFPBedLevelOffsets))completionHandler { 113 | dispatch_after(dispatch_time(0, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 114 | completionHandler(YES, (TFPBedLevelOffsets){-0.30, -0.4, -0.65, -1, -0.95}); 115 | }); 116 | } 117 | 118 | 119 | - (void)establishConnectionWithCompletionHandler:(void(^)(NSError *error))completionHandler { 120 | self.pendingConnection = YES; 121 | dispatch_after(dispatch_time(0, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 122 | self.serialNumber = @"TEST-00-00-00-00-123-456"; 123 | self.pendingConnection = NO; 124 | if(completionHandler) { 125 | completionHandler(nil); 126 | } 127 | }); 128 | }; 129 | 130 | 131 | - (void)setBedOffsets:(TFPBedLevelOffsets)offsets completionHandler:(void (^)(BOOL))completionHandler { 132 | TFLog(@"Dry run setBedOffsets: %@", TFPBedLevelOffsetsDescription(offsets)); 133 | [super setBedOffsets:offsets completionHandler:completionHandler]; 134 | } 135 | 136 | 137 | - (double)speedMultiplier { 138 | return speedMultiplier; 139 | } 140 | 141 | 142 | + (void)setSpeedMultiplier:(double)multiplier { 143 | speedMultiplier = multiplier; 144 | } 145 | 146 | 147 | @end 148 | -------------------------------------------------------------------------------- /microprint/TFPDryRunPrinterConnection.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPDryRunPrinterConnection.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Mon 2015-08-24. 6 | // Copyright © 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPPrinterConnection.h" 10 | 11 | @interface TFPDryRunPrinterConnection : TFPPrinterConnection 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /microprint/TFPDryRunPrinterConnection.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPDryRunPrinterConnection.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Mon 2015-08-24. 6 | // Copyright © 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPDryRunPrinterConnection.h" 10 | #import "TFPGCode.h" 11 | #import "TFPGCodeHelpers.h" 12 | #import "TFPExtras.h" 13 | #import "TFPPrinter+VirtualEEPROM.h" 14 | 15 | 16 | @interface TFPPrinterConnection (Private) 17 | - (void)processIncomingString:(NSString*)incomingLine; 18 | @property dispatch_queue_t serialPortQueue; 19 | @property (readwrite) TFPPrinterConnectionState state; 20 | - (void)finishEstablishment; 21 | @property (copy) void(^connectionCompletionHandler)(NSError *error); 22 | @end 23 | 24 | 25 | 26 | @implementation TFPDryRunPrinterConnection 27 | 28 | 29 | - (instancetype)init { 30 | return [super initWithSerialPort:nil]; 31 | } 32 | 33 | 34 | - (void)sendGCode:(TFPGCode*)code { 35 | NSInteger M = [code valueForField:'M' fallback:-1]; 36 | NSDictionary *values = nil; 37 | 38 | switch(M) { 39 | case 115: 40 | values = @{@"X-SERIAL_NUMBER": @"DRYRUN0000123456"}; 41 | break; 42 | 43 | case 619: { 44 | NSInteger index = [code valueForField:'S']; 45 | float value = 0; 46 | 47 | switch(index) { 48 | case VirtualEEPROMIndexBacklashCompensationX: 49 | value = 0.33; 50 | break; 51 | case VirtualEEPROMIndexBacklashCompensationY: 52 | value = 0.88; 53 | break; 54 | case VirtualEEPROMIndexBacklashCompensationSpeed: 55 | value = 1500; 56 | break; 57 | } 58 | 59 | values = @{@"DT": [NSString stringWithFormat:@"%d", [TFPPrinter encodeVirtualEEPROMIntegerValueForFloat:value]]}; 60 | break; 61 | } 62 | 63 | case 105: 64 | dispatch_after(dispatch_time(0, 0.1 * NSEC_PER_SEC), self.serialPortQueue, ^{ 65 | [self processIncomingString:@"T:300"]; 66 | }); 67 | break; 68 | } 69 | 70 | dispatch_after(dispatch_time(0, 0.01 * NSEC_PER_SEC), self.serialPortQueue, ^{ 71 | [self respondOKWithValues:values toCode:code]; 72 | }); 73 | } 74 | 75 | 76 | - (void)respondOKWithValues:(NSDictionary*)values toCode:(TFPGCode*)code { 77 | NSString *valueString = [[values.allKeys tf_mapWithBlock:^id(NSString *key) { 78 | return [NSString stringWithFormat:@"%@:%@", key, values[key]]; 79 | }] componentsJoinedByString:@" "] ?: @""; 80 | NSString *lineNumber = [code hasField:'N'] ? [NSString stringWithFormat:@"%hd", code.N] : @""; 81 | NSString *response = [NSString stringWithFormat:@"ok %@ %@", lineNumber, valueString]; 82 | 83 | [self processIncomingString:response]; 84 | } 85 | 86 | 87 | - (void)openWithCompletionHandler:(void(^)(NSError *error))completionHandler { 88 | self.state = TFPPrinterConnectionStatePending; 89 | self.connectionCompletionHandler = completionHandler; 90 | 91 | dispatch_after(dispatch_time(0, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 92 | [self finishEstablishment]; 93 | }); 94 | } 95 | 96 | 97 | @end -------------------------------------------------------------------------------- /microprint/TFPExtras.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPExtras.h 3 | // MicroPrint 4 | // 5 | // 6 | 7 | @import Foundation; 8 | @import CoreGraphics; 9 | #import "ORSSerialPort.h" 10 | 11 | 12 | @interface NSArray (TFPExtras) 13 | - (NSArray*)tf_mapWithBlock:(id(^)(id object))function; 14 | - (NSArray*)tf_selectWithBlock:(BOOL(^)(id object))function; 15 | - (NSArray*)tf_rejectWithBlock:(BOOL(^)(id object))function; 16 | - (NSSet*)tf_set; 17 | @end 18 | 19 | 20 | @interface NSData (TFPExtras) 21 | + (instancetype)tf_singleByte:(uint8_t)byte; 22 | 23 | @property (readonly) NSData *tf_fletcher16Checksum; 24 | - (NSUInteger)tf_offsetOfData:(NSData*)subdata; 25 | - (NSData *)tf_dataByDecodingDeflate; 26 | @end 27 | 28 | 29 | @interface NSIndexSet (TFPExtras) 30 | + (NSIndexSet*)tf_indexSetWithIndexes:(NSInteger)firstIndex, ...; // Terminate with negative 31 | + (NSIndexSet*)ww_indexSetFromArray:(NSArray *)source; 32 | @end 33 | 34 | 35 | extern NSString *const TFPErrorDomain; 36 | extern NSString *const TFPErrorGCodeStringKey; 37 | extern NSString *const TFPErrorGCodeKey; 38 | extern NSString *const TFPErrorGCodeLineKey; 39 | 40 | 41 | enum TFPErrorCodes { 42 | TFPErrorCodeParseError = 1, 43 | TFPErrorCodeIncompatibleCode, 44 | TFPScriptExecutionError, 45 | }; 46 | 47 | 48 | extern void TFLog(NSString *format, ...); 49 | extern uint64_t TFNanosecondTime(void); 50 | 51 | extern CGFloat TFPVectorDot(CGVector a, CGVector b); 52 | 53 | extern void TFAssertMainThread(); 54 | extern void TFMainThread(void(^block)()); -------------------------------------------------------------------------------- /microprint/TFPExtras.m: -------------------------------------------------------------------------------- 1 | // 2 | // Extras.m 3 | // MicroPrint 4 | // 5 | // 6 | 7 | #import "TFPExtras.h" 8 | #import "zlib.h" 9 | @import MachO; 10 | 11 | 12 | NSString *const TFPErrorDomain = @"TFPErrorDomain"; 13 | NSString *const TFPErrorGCodeStringKey = @"GCodeString"; 14 | NSString *const TFPErrorGCodeKey = @"GCode"; 15 | NSString *const TFPErrorGCodeLineKey = @"GCodeLine"; 16 | 17 | 18 | @implementation NSArray (TFPExtras) 19 | 20 | - (NSArray*)tf_mapWithBlock:(id(^)(id object))function { 21 | NSMutableArray *array = [NSMutableArray new]; 22 | for(id object in self) { 23 | id value = function(object); 24 | if(value) { 25 | [array addObject:value]; 26 | } 27 | } 28 | return array; 29 | } 30 | 31 | 32 | - (NSArray*)tf_selectWithBlock:(BOOL(^)(id object))function { 33 | NSMutableArray *array = [NSMutableArray new]; 34 | for(id object in self) { 35 | if(function(object)) { 36 | [array addObject:object]; 37 | } 38 | } 39 | return array; 40 | } 41 | 42 | 43 | - (NSArray*)tf_rejectWithBlock:(BOOL(^)(id object))function { 44 | return [self tf_selectWithBlock:^BOOL(id object) { 45 | return !function(object); 46 | }]; 47 | } 48 | 49 | 50 | - (NSSet*)tf_set { 51 | return [NSSet setWithArray:self]; 52 | } 53 | 54 | 55 | @end 56 | 57 | 58 | 59 | @implementation NSData (TFPExtras) 60 | 61 | 62 | + (instancetype)tf_singleByte:(uint8_t)byte { 63 | return [NSData dataWithBytes:&byte length:1]; 64 | } 65 | 66 | 67 | - (NSData*)tf_fletcher16Checksum { 68 | uint8_t check1 = 0; 69 | uint8_t check2 = 0; 70 | 71 | const uint8_t *bytes = self.bytes; 72 | for(int i = 0; i < self.length; i++) { 73 | uint8_t byte = bytes[i]; 74 | check1 = (check1 + byte) % 255; 75 | check2 = (check2 + check1) % 255; 76 | } 77 | 78 | NSMutableData *checksum = [NSMutableData data]; 79 | [checksum appendBytes:&check1 length:sizeof(check1)]; 80 | [checksum appendBytes:&check2 length:sizeof(check2)]; 81 | return checksum; 82 | } 83 | 84 | 85 | - (NSUInteger)tf_offsetOfData:(NSData*)subdata { 86 | return [self rangeOfData:subdata options:0 range:NSMakeRange(0, self.length)].location; 87 | } 88 | 89 | 90 | - (NSData *)tf_dataByDecodingDeflate { 91 | NSData *data = self; 92 | if ([data length] == 0) return data; 93 | 94 | NSUInteger full_length = [data length]; 95 | NSUInteger half_length = [data length] / 2; 96 | 97 | NSMutableData *decompressed = [NSMutableData dataWithLength:full_length + half_length]; 98 | BOOL done = NO; 99 | int status; 100 | 101 | z_stream strm; 102 | strm.next_in = (Bytef *)[data bytes]; 103 | strm.avail_in = (uInt)[data length]; 104 | strm.total_out = 0; 105 | strm.zalloc = Z_NULL; 106 | strm.zfree = Z_NULL; 107 | 108 | if (inflateInit2(&strm, (15+32)) != Z_OK) return nil; 109 | while (!done) { 110 | // Make sure we have enough room and reset the lengths. 111 | if (strm.total_out >= [decompressed length]) 112 | [decompressed increaseLengthBy: half_length]; 113 | strm.next_out = [decompressed mutableBytes] + strm.total_out; 114 | strm.avail_out = (uInt)([decompressed length] - strm.total_out); 115 | 116 | // Inflate another chunk. 117 | status = inflate (&strm, Z_SYNC_FLUSH); 118 | if (status == Z_STREAM_END) done = YES; 119 | else if (status != Z_OK) break; 120 | } 121 | if (inflateEnd (&strm) != Z_OK) return nil; 122 | 123 | // Set real length. 124 | if (done) { 125 | [decompressed setLength:strm.total_out]; 126 | return [NSData dataWithData: decompressed]; 127 | } else { 128 | return nil; 129 | } 130 | } 131 | 132 | 133 | @end 134 | 135 | 136 | @implementation NSIndexSet (TFPExtras) 137 | 138 | 139 | + (NSIndexSet*)tf_indexSetWithIndexes:(NSInteger)firstIndex, ... { 140 | va_list list; 141 | va_start(list, firstIndex); 142 | 143 | NSMutableIndexSet *indexes = [NSMutableIndexSet indexSetWithIndex:firstIndex]; 144 | NSInteger index; 145 | while((index = va_arg(list, int)) >= 0) { 146 | [indexes addIndex:index]; 147 | } 148 | 149 | va_end(list); 150 | return indexes; 151 | } 152 | 153 | + (NSIndexSet*)ww_indexSetFromArray:(NSArray *)source { 154 | 155 | NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet]; 156 | 157 | for (NSNumber *index in source) { 158 | [indexes addIndex:index.intValue]; 159 | } 160 | 161 | return indexes; 162 | } 163 | 164 | 165 | @end 166 | 167 | 168 | void TFLog(NSString *format, ...) { 169 | va_list list; 170 | va_start(list, format); 171 | NSString *string = [[NSString alloc] initWithFormat:format arguments:list]; 172 | va_end(list); 173 | printf("%s\n", string.UTF8String); 174 | } 175 | 176 | 177 | uint64_t TFNanosecondTime(void) { 178 | mach_timebase_info_data_t info; 179 | mach_timebase_info(&info); 180 | return (mach_absolute_time() * info.numer) / info.denom; 181 | } 182 | 183 | 184 | CGFloat TFPVectorDot(CGVector a, CGVector b) { 185 | return a.dx * b.dx + a.dy * b.dy; 186 | } 187 | 188 | 189 | void TFAssertMainThread() { 190 | NSCAssert([NSThread isMainThread], @"Whoa. This should be on the main thread but isn't!"); 191 | } 192 | 193 | 194 | void TFMainThread(void(^block)()) { 195 | if([NSThread isMainThread]) { 196 | block(); 197 | }else{ 198 | dispatch_async(dispatch_get_main_queue(), block); 199 | } 200 | } -------------------------------------------------------------------------------- /microprint/TFPExtrusionOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPExtrusionOperation.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sun 2015-06-28. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TFPOperation.h" 11 | 12 | 13 | @interface TFPExtrusionOperation : TFPOperation 14 | - (instancetype)initWithPrinter:(TFPPrinter*)printer retraction:(BOOL)retract; 15 | 16 | @property double temperature; 17 | 18 | @property (copy) void(^preparationProgressBlock)(double temperature); 19 | @property (copy) void(^extrusionStartedBlock)(); 20 | @property (copy) void(^extrusionStoppedBlock)(); 21 | @end -------------------------------------------------------------------------------- /microprint/TFPExtrusionOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPExtrusionOperation.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sun 2015-06-28. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPExtrusionOperation.h" 10 | #import "TFPExtras.h" 11 | #import "TFPGCodeHelpers.h" 12 | #import "TFP3DVector.h" 13 | 14 | #import "TFAsyncOperationCoalescer.h" 15 | #import "MAKVONotificationCenter.h" 16 | 17 | 18 | static const double extrudeStepLength = 0.5; 19 | static const double extrudeFeedRate = 210; 20 | static const double minimumZLevelForOperation = 25; 21 | 22 | 23 | 24 | @interface TFPExtrusionOperation () 25 | @property BOOL retract; 26 | @property BOOL stopped; 27 | 28 | @property (readwrite) TFPOperationStage stage; 29 | 30 | @property (copy) void(^cancelHeatingBlock)(); 31 | @property (copy) void(^cancelMovingBlock)(); 32 | @end 33 | 34 | 35 | 36 | @implementation TFPExtrusionOperation 37 | @synthesize stage=_stage; 38 | 39 | 40 | - (instancetype)initWithPrinter:(TFPPrinter*)printer retraction:(BOOL)retract { 41 | if(!(self = [super initWithPrinter:printer])) return nil; 42 | 43 | if(retract) { 44 | self.temperature = 275; 45 | }else{ 46 | self.temperature = 230; 47 | } 48 | self.retract = retract; 49 | 50 | return self; 51 | } 52 | 53 | 54 | - (void)extrudeStep { 55 | __weak __typeof__(self) weakSelf = self; 56 | double extrusionLength = self.retract ? -extrudeStepLength : extrudeStepLength; 57 | 58 | [self.printer sendGCode:[TFPGCode codeForExtrusion:extrusionLength feedRate:extrudeFeedRate] responseHandler:^(BOOL success, NSDictionary *value) { 59 | if(!weakSelf.stopped) { 60 | [weakSelf extrudeStep]; 61 | } 62 | }]; 63 | } 64 | 65 | 66 | - (void)stop { 67 | if(self.cancelHeatingBlock || self.cancelMovingBlock) { 68 | // Prep stage 69 | if(self.cancelHeatingBlock) 70 | self.cancelHeatingBlock(); 71 | if(self.cancelMovingBlock) 72 | self.cancelMovingBlock(); 73 | 74 | self.cancelMovingBlock = nil; 75 | self.cancelHeatingBlock = nil; 76 | 77 | [self runEndCodeIncludingRetraction:NO]; 78 | }else{ 79 | [self runEndCodeIncludingRetraction:YES]; 80 | } 81 | 82 | self.stopped = YES; 83 | } 84 | 85 | 86 | - (void)runEndCodeIncludingRetraction:(BOOL)retractIfNeeded { 87 | __weak __typeof__(self) weakSelf = self; 88 | 89 | NSMutableArray *steps = [@[ 90 | [TFPGCode absoluteModeCode], 91 | [TFPGCode codeForTurningOffHeater], 92 | [TFPGCode turnOffFanCode], 93 | [TFPGCode turnOffMotorsCode], 94 | ] mutableCopy]; 95 | if(!self.retract && retractIfNeeded) { 96 | [steps insertObject:[TFPGCode codeForExtrusion:-2 feedRate:extrudeFeedRate] atIndex:0]; 97 | } 98 | 99 | self.stage = TFPOperationStageEnding; 100 | 101 | TFPGCodeProgram *end = [TFPGCodeProgram programWithLines:steps]; 102 | [self.context runGCodeProgram:end completionHandler:^(BOOL success, NSArray *valueDictionaries) { 103 | if(weakSelf.extrusionStoppedBlock) { 104 | weakSelf.extrusionStoppedBlock(); 105 | } 106 | [self ended]; 107 | }]; 108 | } 109 | 110 | 111 | 112 | - (BOOL)start { 113 | if(![super start]) { 114 | return NO; 115 | } 116 | self.stage = TFPOperationStagePreparation; 117 | 118 | __weak TFPPrinter *printer = self.printer; 119 | __weak __typeof__(self) weakSelf = self; 120 | 121 | 122 | [self.context sendGCode:[TFPGCode codeForSettingFanSpeed:255] responseHandler:nil]; 123 | [self.context sendGCode:[TFPGCode absoluteModeCode] responseHandler:nil]; 124 | 125 | 126 | TFAsyncOperationCoalescer *coalescer = [TFAsyncOperationCoalescer new]; 127 | 128 | void(^heatingProgressBlock)(double progress) = [coalescer addOperation]; 129 | self.cancelHeatingBlock = [self.context setHeaterTemperatureAsynchronously:self.temperature progressBlock:^(double currentTemperature) { 130 | heatingProgressBlock(currentTemperature / weakSelf.temperature); 131 | } completionBlock:^{ 132 | heatingProgressBlock(1); 133 | weakSelf.cancelHeatingBlock = nil; 134 | }]; 135 | 136 | 137 | TFP3DVector *raisedPosition = [TFP3DVector zVector:MAX(self.printer.position.z, minimumZLevelForOperation)]; 138 | 139 | void(^moveProgressBlock)(double progress) = [coalescer addOperation]; 140 | self.cancelMovingBlock = [self.context moveAsynchronouslyToPosition:raisedPosition feedRate:2900 progressBlock:^(double fraction, TFP3DVector *position) { 141 | moveProgressBlock(fraction); 142 | } completionBlock:^{ 143 | moveProgressBlock(1); 144 | weakSelf.cancelMovingBlock = nil; 145 | }]; 146 | 147 | coalescer.progressUpdateBlock = ^(double progress) { 148 | if(weakSelf.preparationProgressBlock) { 149 | weakSelf.preparationProgressBlock(progress); 150 | } 151 | }; 152 | 153 | coalescer.completionBlock = ^{ 154 | if(weakSelf.extrusionStartedBlock) { 155 | weakSelf.extrusionStartedBlock(); 156 | } 157 | weakSelf.stage = TFPOperationStageRunning; 158 | 159 | [printer sendGCode:[TFPGCode relativeModeCode] responseHandler:nil]; 160 | [weakSelf extrudeStep]; 161 | }; 162 | 163 | return YES; 164 | } 165 | 166 | 167 | - (TFPOperationKind)kind { 168 | return TFPOperationKindUtility; 169 | } 170 | 171 | 172 | - (NSString *)activityDescription { 173 | return self.retract ? @"Retracting" : @"Extruding"; 174 | } 175 | 176 | 177 | @end -------------------------------------------------------------------------------- /microprint/TFPFilament.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPFilament.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sat 2015-07-11. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | 12 | typedef NS_ENUM(NSUInteger, TFPFilamentType) { 13 | TFPFilamentTypeUnknown = 0, 14 | TFPFilamentTypePLA = 'PLA ', 15 | TFPFilamentTypeABS = 'ABS ', 16 | TFPFilamentTypeHIPS = 'HIPS', 17 | TFPFilamentTypeOther = 'othr', 18 | }; 19 | 20 | 21 | 22 | @interface TFPFilament : NSObject 23 | + (instancetype)defaultFilament; 24 | + (instancetype)filamentForType:(TFPFilamentType)type; 25 | 26 | + (TFPFilamentType)typeForString:(NSString*)string; 27 | 28 | @property (readonly) TFPFilamentType type; 29 | @property (readonly, copy) NSString *name; 30 | 31 | @property (readonly) double defaultTemperature; 32 | 33 | @property (readonly) NSUInteger fanSpeed; 34 | @property (readonly) double temperatureIncreaseForFirstLayer; 35 | @end 36 | -------------------------------------------------------------------------------- /microprint/TFPFilament.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPFilament.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sat 2015-07-11. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPFilament.h" 10 | 11 | 12 | @interface TFPFilament () 13 | @property (readwrite) TFPFilamentType type; 14 | @property (readwrite, copy) NSString *name; 15 | 16 | @property (readwrite) double defaultTemperature; 17 | @end 18 | 19 | 20 | 21 | @implementation TFPFilament 22 | 23 | 24 | + (NSDictionary*)filamentSpecification { 25 | return @{ 26 | @(TFPFilamentTypePLA): 27 | @{ 28 | @"name": @"PLA", 29 | @"temperature": @215, 30 | }, 31 | @(TFPFilamentTypeABS): 32 | @{ 33 | @"name": @"ABS", 34 | @"temperature": @275, 35 | }, 36 | @(TFPFilamentTypeHIPS): 37 | @{ 38 | @"name": @"HIPS", 39 | @"temperature": @265, 40 | }, 41 | @(TFPFilamentTypeOther): 42 | @{ 43 | @"name": @"Other", 44 | @"temperature": @215, 45 | }, 46 | }; 47 | } 48 | 49 | 50 | + (instancetype)defaultFilament { 51 | return [self filamentForType:TFPFilamentTypePLA]; 52 | } 53 | 54 | 55 | + (instancetype)filamentForType:(TFPFilamentType)type { 56 | return [[self alloc] initWithType:type data:[self filamentSpecification][@(type)]]; 57 | } 58 | 59 | 60 | + (TFPFilamentType)typeForString:(NSString*)string { 61 | NSDictionary *names = @{ 62 | @"pla" : @(TFPFilamentTypePLA), 63 | @"abs" : @(TFPFilamentTypeABS), 64 | @"hips" : @(TFPFilamentTypeHIPS), 65 | @"other" : @(TFPFilamentTypeOther), 66 | }; 67 | NSNumber *type = names[string.lowercaseString]; 68 | return type ? type.integerValue : TFPFilamentTypeUnknown; 69 | } 70 | 71 | 72 | - (instancetype)initWithType:(TFPFilamentType)type data:(NSDictionary*)spec { 73 | if(!spec) { 74 | return nil; 75 | } 76 | 77 | if(!(self = [super init])) return nil; 78 | 79 | self.type = type; 80 | self.name = spec[@"name"]; 81 | self.defaultTemperature = [spec[@"temperature"] doubleValue]; 82 | 83 | return self; 84 | } 85 | 86 | 87 | - (NSUInteger)fanSpeed { 88 | return (self.type == TFPFilamentTypePLA) ? 255 : 50; 89 | } 90 | 91 | 92 | - (double)temperatureIncreaseForFirstLayer { 93 | return (self.type == TFPFilamentTypePLA) ? 10 : 15; 94 | } 95 | 96 | 97 | @end -------------------------------------------------------------------------------- /microprint/TFPGCode.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFGCodeLine.h 3 | // MicroPrint 4 | // 5 | // 6 | 7 | #import 8 | 9 | @interface TFPGCode : NSObject 10 | + (instancetype)codeWithString:(NSString*)string; 11 | - (instancetype)initWithString:(NSString*)string; 12 | 13 | + (instancetype)codeWithField:(char)field value:(double)value; 14 | + (instancetype)codeWithComment:(NSString*)string; 15 | 16 | - (TFPGCode*)codeBySettingField:(char)field toValue:(double)value; 17 | - (TFPGCode*)codeByAdjustingField:(char)field offset:(double)offset; 18 | - (TFPGCode*)codeBySettingComment:(NSString*)comment; 19 | 20 | @property (readonly, copy) NSString *comment; 21 | @property (readonly) BOOL hasFields; 22 | - (void)enumerateFieldsWithBlock:(void(^)(char field, double value, BOOL *stopFlag))block; 23 | 24 | - (BOOL)hasField:(char)field; 25 | - (double)valueForField:(char)field; 26 | - (double)valueForField:(char)field fallback:(double)fallbackValue; 27 | - (NSNumber*)numberForField:(char)field; 28 | 29 | @property (nonatomic, readonly) int16_t N; 30 | 31 | @property (nonatomic, readonly) uint16_t M; 32 | @property (nonatomic, readonly) uint16_t G; 33 | 34 | @property (nonatomic, readonly) float X; 35 | @property (nonatomic, readonly) float Y; 36 | @property (nonatomic, readonly) float Z; 37 | @property (nonatomic, readonly) float E; 38 | @property (nonatomic, readonly) float F; 39 | 40 | @property (nonatomic, readonly) uint32_t S; 41 | @property (nonatomic, readonly) uint32_t P; 42 | 43 | @property (readonly) NSData *repetierV2Representation; 44 | @property (readonly) NSString *ASCIIRepresentation; 45 | @end -------------------------------------------------------------------------------- /microprint/TFPGCodeHelpers.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPGCodeHelpers.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Mon 2015-07-13. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPGCode.h" 10 | #import "TFPGCodeProgram.h" 11 | 12 | @class TFP3DVector; 13 | 14 | 15 | @interface TFPGCode (TFPHelpers) 16 | + (instancetype)stopCode; 17 | + (instancetype)waitCodeWithDuration:(NSTimeInterval)seconds; 18 | + (instancetype)waitForCompletionCode; 19 | + (instancetype)findZeroCode; 20 | 21 | // Line numbering 22 | + (instancetype)codeForSettingLineNumber:(uint16_t)lineNumber; 23 | - (instancetype)codeBySettingLineNumber:(uint16_t)lineNumber; 24 | 25 | // Feed rates 26 | + (instancetype)codeForSettingFeedRate:(double)feedRate; 27 | 28 | // Motors 29 | + (instancetype)turnOnMotorsCode; 30 | + (instancetype)turnOffMotorsCode; 31 | 32 | // Positioning 33 | + (instancetype)absoluteModeCode; 34 | + (instancetype)relativeModeCode; 35 | + (instancetype)codeForResettingPosition:(TFP3DVector*)position extrusion:(NSNumber*)E; 36 | 37 | // Moving 38 | + (instancetype)moveHomeCode; 39 | + (instancetype)moveWithPosition:(TFP3DVector*)position extrusion:(NSNumber*)E feedRate:(double)F; 40 | + (instancetype)moveWithPosition:(TFP3DVector*)position feedRate:(double)feedRate; 41 | + (instancetype)codeForGettingPosition; 42 | 43 | // Extrusion 44 | + (instancetype)codeForExtrusion:(double)E feedRate:(double)feedRate; 45 | + (instancetype)resetExtrusionCode; 46 | 47 | // Heater 48 | + (instancetype)codeForHeaterTemperature:(double)temperature waitUntilDone:(BOOL)wait; 49 | + (instancetype)codeForTurningOffHeater; 50 | + (instancetype)codeForReadingHeaterTemperature; 51 | 52 | // Fan 53 | + (instancetype)turnOnFanCode; 54 | + (instancetype)turnOffFanCode; 55 | + (instancetype)codeForSettingFanSpeed:(double)speed; 56 | 57 | // Virtual EEPROM 58 | + (instancetype)codeForReadingVirtualEEPROMAtIndex:(NSUInteger)valueIndex; 59 | + (instancetype)codeForWritingVirtualEEPROMAtIndex:(NSUInteger)valueIndex value:(int32_t)value; 60 | 61 | @property (readonly) NSInteger layerIndexFromComment; 62 | 63 | @property (readonly) TFP3DVector *movementVector; 64 | @end 65 | 66 | 67 | typedef NS_ENUM(NSUInteger, TFPPrintPhase) { 68 | TFPPrintPhaseInvalid, 69 | TFPPrintPhaseSkirt, 70 | TFPPrintPhaseAdhesion, 71 | TFPPrintPhaseModel, 72 | }; 73 | 74 | 75 | @interface TFPPrintLayer : NSObject 76 | @property (readonly) NSInteger layerIndex; 77 | @property (readonly) TFPPrintPhase phase; 78 | @property (readonly) NSRange lineRange; 79 | @property (readonly) double minZ; 80 | @property (readonly) double maxZ; 81 | @end 82 | 83 | 84 | typedef struct { 85 | double x; 86 | double y; 87 | double z; 88 | double e; 89 | } TFPAbsolutePosition; 90 | 91 | 92 | 93 | typedef struct { 94 | double x; 95 | double y; 96 | double z; 97 | double xSize; 98 | double ySize; 99 | double zSize; 100 | } TFPCuboid; 101 | 102 | 103 | extern double TFPAbsolutePositionDistance(TFPAbsolutePosition a, TFPAbsolutePosition b); 104 | 105 | extern BOOL TFPCuboidContainsPosition(TFPCuboid cuboid, TFPAbsolutePosition position); 106 | extern BOOL TFPCuboidContainsCuboid(TFPCuboid outer, TFPCuboid inner); 107 | extern TFPCuboid TFPCuboidInfinite; 108 | 109 | extern TFPCuboid TFPCuboidM3DMicroPrintVolumeLower; 110 | extern TFPCuboid TFPCuboidM3DMicroPrintVolumeUpper; 111 | 112 | extern double TFPBoundedTemperature(double temperature); 113 | extern BOOL TFPTemperatureWithinBounds(double temperature); 114 | 115 | @interface TFPGCodeProgram (TFPHelpers) 116 | - (TFPCuboid)measureBoundingBoxWithinBox:(TFPCuboid)limit; 117 | - (TFPCuboid)measureBoundingBox; 118 | - (BOOL)withinM3DMicroPrintableVolume; 119 | 120 | - (void)enumerateMovesWithBlock:(void(^)(TFPAbsolutePosition from, TFPAbsolutePosition to, double feedRate, TFPGCode *code, NSUInteger index))block; 121 | 122 | - (BOOL)validateForM3D:(NSError**)error; 123 | 124 | // Keys are TFPPrintPhases; values are NSRanges 125 | - (NSDictionary *)determinePhaseRanges; 126 | 127 | - (NSArray *)determineLayers; 128 | @end -------------------------------------------------------------------------------- /microprint/TFPGCodeProgram.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFGCodeProgram.h 3 | // MicroPrint 4 | // 5 | 6 | @import Foundation; 7 | @class TFP3DVector, TFPGCode; 8 | 9 | 10 | @interface TFPGCodeProgram : NSObject 11 | + (instancetype)programWithLines:(NSArray *)lines; 12 | - (instancetype)initWithLines:(NSArray *)lines; 13 | - (instancetype)initWithString:(NSString*)string error:(NSError**)outError; 14 | - (instancetype)initWithFileURL:(NSURL*)URL error:(NSError**)outError; 15 | 16 | @property (copy, readonly) NSArray *lines; 17 | 18 | - (BOOL)writeToFileURL:(NSURL*)URL error:(NSError**)outError; 19 | - (NSString *)ASCIIRepresentation; 20 | @end -------------------------------------------------------------------------------- /microprint/TFPGCodeProgram.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFGCodeProgram.m 3 | // MicroPrint 4 | // 5 | // 6 | 7 | #import "TFPGCodeProgram.h" 8 | #import "TFPGCode.h" 9 | #import "TFPExtras.h" 10 | 11 | @interface TFPGCodeProgram () 12 | @property (copy, readwrite) NSArray *lines; 13 | @end 14 | 15 | 16 | @implementation TFPGCodeProgram 17 | 18 | 19 | - (instancetype)initWithLines:(NSArray *)lines { 20 | if(!(self = [super init])) return nil; 21 | 22 | self.lines = lines; 23 | 24 | return self; 25 | } 26 | 27 | 28 | + (instancetype)programWithLines:(NSArray *)lines { 29 | return [[self alloc] initWithLines:lines]; 30 | } 31 | 32 | 33 | - (instancetype)initWithString:(NSString*)string error:(NSError**)outError { 34 | NSMutableArray *lines = [NSMutableArray new]; 35 | __block BOOL failed = NO; 36 | __block NSString *failedLine; 37 | 38 | [string enumerateLinesUsingBlock:^(NSString *lineString, BOOL *stop) { 39 | TFPGCode *line = [[TFPGCode alloc] initWithString:lineString]; 40 | if(!line) { 41 | *stop = YES; 42 | failed = YES; 43 | failedLine = lineString; 44 | return; 45 | } 46 | [lines addObject:line]; 47 | }]; 48 | 49 | if(failed) { 50 | if(outError) { 51 | NSString *errorString = [NSString stringWithFormat:@"Failed to parse G-code line:\n%@", failedLine]; 52 | *outError = [NSError errorWithDomain:TFPErrorDomain code:TFPErrorCodeParseError userInfo:@{TFPErrorGCodeStringKey: failedLine, NSLocalizedRecoverySuggestionErrorKey: errorString}]; 53 | } 54 | return nil; 55 | } 56 | 57 | return [self initWithLines:lines]; 58 | } 59 | 60 | 61 | - (instancetype)initWithFileURL:(NSURL*)URL error:(NSError**)outError { 62 | NSString *string = [NSString stringWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:NULL]; 63 | if(!string) { 64 | if(outError) { 65 | NSString *errorString = @"Failed to parse G-code file. Invalid character encoding?"; 66 | *outError = [NSError errorWithDomain:TFPErrorDomain code:TFPErrorCodeParseError userInfo:@{NSLocalizedRecoverySuggestionErrorKey: errorString}]; 67 | } 68 | return nil; 69 | } 70 | 71 | return [self initWithString:string error:outError]; 72 | } 73 | 74 | 75 | - (BOOL)writeToFileURL:(NSURL*)URL error:(NSError**)outError { 76 | return [[self ASCIIRepresentation] writeToURL:URL atomically:YES encoding:NSUTF8StringEncoding error:outError]; 77 | } 78 | 79 | 80 | - (NSString *)ASCIIRepresentation { 81 | return [[self.lines valueForKey:@"ASCIIRepresentation"] componentsJoinedByString:@"\n"]; 82 | } 83 | 84 | 85 | - (NSString *)description { 86 | return [[self.lines valueForKey:@"description"] componentsJoinedByString:@"\n"]; 87 | } 88 | 89 | 90 | @end -------------------------------------------------------------------------------- /microprint/TFPOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPOperation.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sat 2015-07-11. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "TFPPrinter.h" 11 | 12 | 13 | // Make sure these ones are in sync with MicroPrint.sdef 14 | 15 | typedef NS_ENUM(NSUInteger, TFPOperationKind) { 16 | TFPOperationKindIdle = 'idle', 17 | TFPOperationKindPrintJob = 'prjb', 18 | TFPOperationKindCalibration = 'clbr', 19 | TFPOperationKindUtility = 'util', 20 | }; 21 | 22 | typedef NS_ENUM(NSUInteger, TFPOperationStage) { 23 | TFPOperationStageIdle = 'idle', 24 | TFPOperationStagePreparation = 'prep', 25 | TFPOperationStageRunning = 'rung', 26 | TFPOperationStageEnding = 'endg', 27 | }; 28 | 29 | 30 | @interface TFPOperation : NSObject 31 | - (instancetype)initWithPrinter:(TFPPrinter*)printer; 32 | 33 | @property (readonly, weak) TFPPrinter *printer; 34 | @property (readonly) NSString *activityDescription; 35 | 36 | @property (readonly) TFPOperationKind kind; 37 | @property (readonly) TFPOperationStage stage; 38 | 39 | @property (readonly) TFPPrinterContext *context; 40 | // Override these to customize context: 41 | @property (readonly) TFPPrinterContextOptions printerContextOptions; 42 | @property (readonly) dispatch_queue_t printerContextQueue; 43 | 44 | - (BOOL)start; 45 | - (void)stop; 46 | - (void)ended; 47 | @end 48 | -------------------------------------------------------------------------------- /microprint/TFPOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPOperation.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sat 2015-07-11. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPOperation.h" 10 | 11 | @interface TFPOperation () 12 | @property (readwrite, weak) TFPPrinter *printer; 13 | @property (readwrite) TFPPrinterContext *context; 14 | @end 15 | 16 | 17 | @implementation TFPOperation 18 | 19 | 20 | - (instancetype)initWithPrinter:(TFPPrinter*)printer { 21 | if(!(self = [super init])) return nil; 22 | 23 | self.printer = printer; 24 | 25 | return self; 26 | } 27 | 28 | 29 | - (NSString *)activityDescription { 30 | return @"Doing stuff"; 31 | } 32 | 33 | 34 | - (BOOL)start { 35 | self.context = [self.printer acquireContextWithOptions:[self printerContextOptions] queue:[self printerContextQueue]]; 36 | 37 | if(self.context) { 38 | self.printer.currentOperation = self; 39 | return YES; 40 | } else { 41 | return NO; 42 | } 43 | } 44 | 45 | 46 | - (void)ended { 47 | self.printer.currentOperation = nil; 48 | [self.context invalidate]; 49 | } 50 | 51 | 52 | - (void)stop { 53 | 54 | } 55 | 56 | 57 | - (TFPOperationKind)kind { 58 | return TFPOperationKindIdle; 59 | } 60 | 61 | 62 | - (TFPOperationStage)stage { 63 | return TFPOperationStageRunning; 64 | } 65 | 66 | 67 | - (TFPPrinterContextOptions)printerContextOptions { 68 | return 0; 69 | } 70 | 71 | 72 | - (dispatch_queue_t)printerContextQueue { 73 | return nil; 74 | } 75 | 76 | 77 | @end -------------------------------------------------------------------------------- /microprint/TFPPrintJob.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrintJob.h 3 | // MicroPrint 4 | // 5 | // Created by Tomas Franzén on Thu 2015-06-25. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TFPGCodeProgram.h" 11 | #import "TFPPrintParameters.h" 12 | #import "TFPOperation.h" 13 | 14 | 15 | typedef NS_ENUM(NSUInteger, TFPPrintJobState) { 16 | TFPPrintJobStatePreparing, 17 | TFPPrintJobStateHeating, 18 | TFPPrintJobStatePrinting, 19 | TFPPrintJobStateAborting, 20 | TFPPrintJobStatePausing, 21 | TFPPrintJobStatePaused, 22 | TFPPrintJobStateResuming, 23 | TFPPrintJobStateFinishing, 24 | }; 25 | 26 | 27 | @interface TFPPrintJob : TFPOperation 28 | - (instancetype)initWithProgram:(TFPGCodeProgram*)program printer:(TFPPrinter*)printer printParameters:(TFPPrintParameters*)params; 29 | 30 | @property (readonly) TFPGCodeProgram *program; 31 | 32 | @property (readonly) NSUInteger completedRequests; //Observable 33 | @property (readonly) NSTimeInterval elapsedTime; 34 | 35 | @property (readonly) TFPPrintJobState state; 36 | @property (copy, readonly) NSArray *layers; 37 | 38 | @property (copy) void(^progressBlock)(void); 39 | @property (copy) void(^completionBlock)(void); 40 | @property (copy) void(^abortionBlock)(void); 41 | 42 | - (void)abort; 43 | - (void)pause; 44 | - (void)resume; 45 | @end -------------------------------------------------------------------------------- /microprint/TFPPrintParameters.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrintParameters.h 3 | // MicroPrint 4 | // 5 | // Created by Tomas Franzén on Mon 2015-06-22. 6 | // 7 | 8 | @import Foundation; 9 | #import "TFPFilament.h" 10 | #import "TFPGCodeHelpers.h" 11 | 12 | 13 | typedef struct { 14 | double common; 15 | double backLeft; 16 | double backRight; 17 | double frontRight; 18 | double frontLeft; 19 | } TFPBedLevelOffsets; 20 | 21 | 22 | typedef struct { 23 | double x; 24 | double y; 25 | double speed; 26 | } TFPBacklashValues; 27 | 28 | 29 | extern NSString *TFPBedLevelOffsetsDescription(TFPBedLevelOffsets offsets); 30 | extern NSString *TFPBacklashValuesDescription(TFPBacklashValues values); 31 | 32 | 33 | @interface TFPPrintParameters : NSObject 34 | @property (readwrite) BOOL verbose; 35 | 36 | @property (readwrite) TFPFilament *filament; 37 | @property (readwrite) BOOL useThermalBonding; 38 | @property (readwrite, nonatomic) double temperature; 39 | 40 | @property (readwrite) TFPCuboid boundingBox; 41 | @end -------------------------------------------------------------------------------- /microprint/TFPPrintParameters.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrintParameters.m 3 | // MicroPrint 4 | // 5 | // Created by Tomas Franzén on Mon 2015-06-22. 6 | // 7 | 8 | #import "TFPPrintParameters.h" 9 | 10 | 11 | @implementation TFPPrintParameters 12 | 13 | 14 | - (instancetype)init { 15 | if(!(self = [super init])) return nil; 16 | 17 | self.filament = [TFPFilament defaultFilament]; 18 | self.useThermalBonding = YES; 19 | 20 | return self; 21 | } 22 | 23 | 24 | - (double)temperature { 25 | if(_temperature < DBL_EPSILON) { 26 | return self.filament.defaultTemperature; 27 | }else{ 28 | return _temperature; 29 | } 30 | } 31 | 32 | 33 | @end 34 | 35 | 36 | NSString *TFPBedLevelOffsetsDescription(TFPBedLevelOffsets offsets) { 37 | return [NSString stringWithFormat:@"{ Z: %.02f, BL: %.02f, BR: %.02f, FR: %.02f, FL: %.02f }", 38 | offsets.common, 39 | offsets.backLeft, 40 | offsets.backRight, 41 | offsets.frontRight, 42 | offsets.frontLeft 43 | ]; 44 | } 45 | 46 | 47 | NSString *TFPBacklashValuesDescription(TFPBacklashValues values) { 48 | return [NSString stringWithFormat:@"{ X: %.02f, Y: %.02f, speed: %.0f }", 49 | values.x, 50 | values.y, 51 | values.speed 52 | ]; 53 | } -------------------------------------------------------------------------------- /microprint/TFPPrintStatusController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrintStatusController.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Wed 2015-07-15. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TFPPrintJob.h" 11 | #import "TFPGCodeHelpers.h" 12 | 13 | @interface TFPPrintStatusController : NSObject 14 | - (instancetype)initWithPrintJob:(TFPPrintJob*)printJob; 15 | @property (readonly) TFPPrintJob *printJob; 16 | 17 | // Properties are observable 18 | @property (readonly) NSTimeInterval elapsedTime; 19 | @property (readonly) NSTimeInterval estimatedRemainingTime; 20 | @property (readonly) BOOL hasRemainingTimeEstimate; 21 | 22 | @property (readonly) double printProgress; 23 | @property (readonly) TFPPrintPhase currentPhase; 24 | @property (readonly) double phaseProgress; 25 | @property (readonly) TFPPrintLayer *currentLayer; 26 | @property (readonly) NSUInteger layerCount; 27 | 28 | @property (copy) void(^willMoveHandler)(TFPAbsolutePosition from, TFPAbsolutePosition to, double feedRate, TFPGCode *code); 29 | @property (copy) void(^layerChangeHandler)(); 30 | @end 31 | -------------------------------------------------------------------------------- /microprint/TFPPrinter+VirtualEEPROM.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrinter+VirtualEEPROM.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Thu 2015-07-16. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TFPPrinter.h" 11 | 12 | 13 | enum VirtualEEPROMIndexes { 14 | VirtualEEPROMIndexBacklashCompensationX = 0, 15 | VirtualEEPROMIndexBacklashCompensationY = 1, 16 | 17 | VirtualEEPROMIndexBedCompensationBackRight = 2, 18 | VirtualEEPROMIndexBedCompensationBackLeft = 3, 19 | VirtualEEPROMIndexBedCompensationFrontLeft = 4, 20 | VirtualEEPROMIndexBedCompensationFrontRight = 5, 21 | 22 | VirtualEEPROMIndexFilamentColor = 6, 23 | VirtualEEPROMIndexFilamentTypeID = 7, 24 | VirtualEEPROMIndexFilamentTemperature = 8, 25 | VirtualEEPROMIndexFilamentAmount = 9, 26 | 27 | VirtualEEPROMIndexBacklashExpansionXPlus = 10, 28 | VirtualEEPROMIndexBacklashExpansionYLPlus = 11, 29 | VirtualEEPROMIndexBacklashExpansionYRPlus = 12, 30 | VirtualEEPROMIndexBacklashExpansionYRMinus = 13, 31 | VirtualEEPROMIndexBacklashExpansionZ = 14, 32 | VirtualEEPROMIndexBacklashExpansionE = 15, 33 | 34 | VirtualEEPROMIndexBedOffsetBackLeft = 16, 35 | VirtualEEPROMIndexBedOffsetBackRight = 17, 36 | VirtualEEPROMIndexBedOffsetFrontRight = 18, 37 | VirtualEEPROMIndexBedOffsetFrontLeft = 19, 38 | VirtualEEPROMIndexBedOffsetCommon = 20, 39 | 40 | VirtualEEPROMIndexReservedForSpooler = 21, 41 | 42 | VirtualEEPROMIndexBacklashCompensationSpeed = 22, 43 | 44 | VirtualEEPROMIndexG32Version = 23, 45 | 46 | VirtualEEPROMIndexG32FirstSample = 64, 47 | // ... 48 | VirtualEEPROMIndexG32LastSample = 126, 49 | }; 50 | 51 | 52 | @interface TFPPrinter (VirtualEEPROM) 53 | 54 | + (uint32_t)encodeVirtualEEPROMIntegerValueForFloat:(float)value; 55 | + (float)decodeVirtualEEPROMFloatValueForInteger:(uint32_t)value; 56 | 57 | // Single values, int32 58 | - (void)readVirtualEEPROMValueAtIndex:(NSUInteger)index completionHandler:(void(^)(BOOL success, int32_t value))completionHandler; 59 | - (void)writeVirtualEEPROMValueAtIndex:(NSUInteger)index value:(int32_t)value completionHandler:(void(^)(BOOL success))completionHandler; 60 | 61 | // Single values, converted from/to float 62 | - (void)readVirtualEEPROMFloatValueAtIndex:(NSUInteger)index completionHandler:(void(^)(BOOL success, float value))completionHandler; 63 | - (void)writeVirtualEEPROMFloatValueAtIndex:(NSUInteger)index value:(float)value completionHandler:(void(^)(BOOL success))completionHandler; 64 | 65 | // Multiple values, int32 66 | - (void)readVirtualEEPROMValuesAtIndexes:(NSArray*)indexes completionHandler:(void(^)(BOOL success, NSArray *values))completionHandler; 67 | - (void)writeVirtualEEPROMValues:(NSDictionary*)valuesForIndexes completionHandler:(void(^)(BOOL success))completionHandler; 68 | 69 | // Multiple values, converted from/to float 70 | - (void)readVirtualEEPROMFloatValuesAtIndexes:(NSArray*)indexes completionHandler:(void(^)(BOOL success, NSArray *values))completionHandler; 71 | - (void)writeVirtualEEPROMFloatValues:(NSDictionary*)valuesForIndexes completionHandler:(void(^)(BOOL success))completionHandler; 72 | @end -------------------------------------------------------------------------------- /microprint/TFPPrinter+VirtualEEPROM.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrinter+VirtualEEPROM.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Thu 2015-07-16. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPPrinter+VirtualEEPROM.h" 10 | #import "TFPExtras.h" 11 | #import "TFPGCodeHelpers.h" 12 | 13 | 14 | @implementation TFPPrinter (VirtualEEPROM) 15 | 16 | 17 | + (uint32_t)encodeVirtualEEPROMIntegerValueForFloat:(float)value { 18 | NSSwappedFloat swapped = NSSwapHostFloatToLittle(value); 19 | int32_t intValue; 20 | memcpy(&intValue, &swapped, sizeof(swapped)); 21 | return intValue; 22 | } 23 | 24 | 25 | + (float)decodeVirtualEEPROMFloatValueForInteger:(uint32_t)value { 26 | NSSwappedFloat swapped; 27 | memcpy(&swapped, &value, sizeof(float)); 28 | return NSSwapLittleFloatToHost(swapped); 29 | } 30 | 31 | 32 | - (void)readVirtualEEPROMValueAtIndex:(NSUInteger)index completionHandler:(void(^)(BOOL success, int32_t value))completionHandler { 33 | [self sendGCode:[TFPGCode codeForReadingVirtualEEPROMAtIndex:index] responseHandler:^(BOOL success, NSDictionary *values) { 34 | if(!success) { 35 | completionHandler(NO, 0); 36 | return; 37 | } 38 | completionHandler(YES, [values[@"DT"] intValue]); 39 | }]; 40 | } 41 | 42 | 43 | - (void)writeVirtualEEPROMValueAtIndex:(NSUInteger)index value:(int32_t)value completionHandler:(void(^)(BOOL success))completionHandler { 44 | [self sendGCode:[TFPGCode codeForWritingVirtualEEPROMAtIndex:index value:value] responseHandler:^(BOOL success, NSDictionary *value) { 45 | completionHandler(success); 46 | }]; 47 | } 48 | 49 | 50 | - (void)readVirtualEEPROMFloatValueAtIndex:(NSUInteger)index completionHandler:(void(^)(BOOL success, float value))completionHandler { 51 | [self readVirtualEEPROMValueAtIndex:index completionHandler:^(BOOL success, int32_t value) { 52 | completionHandler(success, [self.class decodeVirtualEEPROMFloatValueForInteger:value]); 53 | }]; 54 | } 55 | 56 | 57 | - (void)writeVirtualEEPROMFloatValueAtIndex:(NSUInteger)index value:(float)value completionHandler:(void(^)(BOOL success))completionHandler { 58 | int32_t intValue = [self.class encodeVirtualEEPROMIntegerValueForFloat:value]; 59 | [self writeVirtualEEPROMValueAtIndex:index value:intValue completionHandler:completionHandler]; 60 | } 61 | 62 | 63 | - (void)readVirtualEEPROMValuesAtIndexes:(NSArray*)indexes completionHandler:(void(^)(BOOL success, NSArray *values))completionHandler { 64 | NSMutableArray *values = [NSMutableArray new]; 65 | [indexes enumerateObjectsUsingBlock:^(NSNumber *indexNumber, NSUInteger index, BOOL *stop) { 66 | [self readVirtualEEPROMValueAtIndex:indexNumber.integerValue completionHandler:^(BOOL success, int32_t value) { 67 | [values addObject:@(value)]; 68 | if(index == indexes.count-1) { 69 | completionHandler(YES, values); 70 | } 71 | }]; 72 | }]; 73 | } 74 | 75 | 76 | - (void)readVirtualEEPROMFloatValuesAtIndexes:(NSArray*)indexes completionHandler:(void(^)(BOOL success, NSArray *values))completionHandler { 77 | [self readVirtualEEPROMValuesAtIndexes:indexes completionHandler:^(BOOL success, NSArray *values) { 78 | NSArray *floatValues = [values tf_mapWithBlock:^NSNumber*(NSNumber *intNumber) { 79 | return @([self.class decodeVirtualEEPROMFloatValueForInteger:intNumber.intValue]); 80 | }]; 81 | 82 | completionHandler(success, floatValues); 83 | }]; 84 | } 85 | 86 | 87 | - (void)writeVirtualEEPROMValues:(NSArray*)values forIndexes:(NSArray*)keys completionHandler:(void(^)(BOOL success))completionHandler { 88 | [keys enumerateObjectsUsingBlock:^(NSNumber *indexNumber, NSUInteger index, BOOL *stop) { 89 | uint32_t value = [values[index] unsignedIntValue]; 90 | 91 | [self writeVirtualEEPROMValueAtIndex:indexNumber.unsignedIntegerValue value:value completionHandler:^(BOOL success) { 92 | if(index == keys.count-1) { 93 | completionHandler(YES); 94 | } 95 | }]; 96 | }]; 97 | } 98 | 99 | 100 | - (void)writeVirtualEEPROMValues:(NSDictionary*)valuesForIndexes completionHandler:(void(^)(BOOL success))completionHandler { 101 | NSMutableArray *keys = [NSMutableArray new]; 102 | NSMutableArray *values = [NSMutableArray new]; 103 | [valuesForIndexes enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, NSNumber *value, BOOL *stop) { 104 | [keys addObject:key]; 105 | [values addObject:value]; 106 | }]; 107 | 108 | [self writeVirtualEEPROMValues:values forIndexes:keys completionHandler:completionHandler]; 109 | } 110 | 111 | 112 | - (void)writeVirtualEEPROMFloatValues:(NSDictionary*)valuesForIndexes completionHandler:(void(^)(BOOL success))completionHandler { 113 | NSMutableDictionary *intValuesForIndexes = [NSMutableDictionary new]; 114 | for(NSNumber *key in valuesForIndexes) { 115 | NSNumber *floatNumber = valuesForIndexes[key]; 116 | intValuesForIndexes[key] = @([self.class encodeVirtualEEPROMIntegerValueForFloat:floatNumber.floatValue]); 117 | } 118 | 119 | [self writeVirtualEEPROMValues:intValuesForIndexes completionHandler:completionHandler]; 120 | } 121 | 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /microprint/TFPPrinter.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrinter.h 3 | // MicroPrint 4 | // 5 | // Created by Tomas Franzén on Tue 2015-06-23. 6 | // 7 | 8 | #import 9 | #import "ORSSerialPort.h" 10 | #import "TFPGCode.h" 11 | #import "TFPPrintParameters.h" 12 | #import "TFPGCodeProgram.h" 13 | 14 | @class TFPOperation, TFPPrinterConnection, TFPPrinterContext; 15 | 16 | 17 | typedef NS_ENUM(NSUInteger, TFPPrinterColor) { 18 | TFPPrinterColorUndetermined, 19 | TFPPrinterColorBlack, 20 | TFPPrinterColorSilver, 21 | TFPPrinterColorLightBlue, 22 | TFPPrinterColorGreen, 23 | TFPPrinterColorOrange, 24 | TFPPrinterColorWhite, 25 | TFPPrinterColorGrape, 26 | TFPPrinterColorOther, 27 | }; 28 | 29 | 30 | typedef NS_ENUM(NSUInteger, TFPPrinterResponseErrorCode) { 31 | TFPPrinterResponseErrorCodeM110MissingLineNumber = 1000, 32 | TFPPrinterResponseErrorCodeCannotColdExtrude, 33 | TFPPrinterResponseErrorCodeCannotCalibrateInUnknownState, 34 | TFPPrinterResponseErrorCodeUnknownGCode, 35 | TFPPrinterResponseErrorCodeUnknownMCode, 36 | TFPPrinterResponseErrorCodeUnknownCommand, 37 | TFPPrinterResponseErrorCodeHeaterFailed, 38 | TFPPrinterResponseErrorCodeMoveTooLarge, 39 | TFPPrinterResponseErrorCodeIdleTimeHeaterAndMotorsTurnedOff, 40 | TFPPrinterResponseErrorCodeTargetAddressOutOfRange, 41 | 42 | TFPPrinterResponseErrorCodeMin = TFPPrinterResponseErrorCodeM110MissingLineNumber, 43 | TFPPrinterResponseErrorCodeMax = TFPPrinterResponseErrorCodeTargetAddressOutOfRange, 44 | }; 45 | 46 | 47 | typedef NS_OPTIONS(NSUInteger, TFPPrinterContextOptions) { 48 | TFPPrinterContextOptionConcurrent = 1<<0, 49 | 50 | TFPPrinterContextOptionDisableLevelCompensation = 1<<1, 51 | TFPPrinterContextOptionDisableBacklashCompensation = 1<<2, 52 | TFPPrinterContextOptionDisableFeedRateConversion = 1<<3, 53 | 54 | TFPPrinterContextOptionDisableCompensation = TFPPrinterContextOptionDisableLevelCompensation | TFPPrinterContextOptionDisableBacklashCompensation, 55 | }; 56 | 57 | 58 | extern const NSString *TFPPrinterResponseErrorCodeKey; 59 | typedef NSDictionary* TFPGCodeResponseDictionary; 60 | 61 | 62 | 63 | @interface TFPPrinter : NSObject 64 | - (instancetype)initWithConnection:(TFPPrinterConnection*)connection; 65 | @property (readonly) TFPPrinterConnection *connection; 66 | 67 | @property TFPOperation *currentOperation; 68 | 69 | - (void)establishConnectionWithCompletionHandler:(void(^)(NSError *error))completionHandler; 70 | - (BOOL)printerShouldBeInvalidatedWithRemovedSerialPorts:(NSArray*)ports; 71 | @property (readonly) BOOL pendingConnection; 72 | 73 | @property (copy) void(^outgoingCodeBlock)(NSString *string); 74 | @property (copy) void(^incomingCodeBlock)(NSString *string); 75 | @property (copy) void(^noticeBlock)(NSString *string); 76 | 77 | - (void)sendNotice:(NSString*)noticeFormat, ...; 78 | 79 | // Sending of G-code. Response queue is main. 80 | // If success is YES, value dictionary contains parameters from OK response 81 | // If success is NO, value dictionary contains an NSNumber-wrapped TFPPrinterResponseErrorCode in TFPPrinterResponseErrorCodeKey 82 | 83 | - (void)sendGCode:(TFPGCode*)code responseHandler:(void(^)(BOOL success, TFPGCodeResponseDictionary value))block; 84 | 85 | - (TFPPrinterContext*)acquireContextWithOptions:(TFPPrinterContextOptions)options queue:(dispatch_queue_t)queue; 86 | 87 | 88 | + (NSString*)descriptionForErrorCode:(TFPPrinterResponseErrorCode)code; 89 | 90 | // State (observable) 91 | @property (readonly) TFPPrinterColor color; 92 | @property (readonly, copy) NSString *serialNumber; 93 | @property (readonly, copy) NSString *firmwareVersion; 94 | @property (readonly) NSComparisonResult firmwareVersionComparedToTestedRange; 95 | 96 | @property (nonatomic) double feedrate; 97 | @property (readonly) double heaterTargetTemperature; 98 | @property (readonly) double heaterTemperature; 99 | 100 | @property (readonly) BOOL hasValidZLevel; 101 | @property (readonly) BOOL hasOutOfBoundsZLevel; 102 | 103 | @property (nonatomic, readonly) TFPBedLevelOffsets bedBaseOffsets; 104 | @property (nonatomic) TFPBedLevelOffsets bedLevelOffsets; 105 | @property (readonly) BOOL hasAllZeroBedLevelOffsets; 106 | 107 | @property (nonatomic) TFPBacklashValues backlashValues; 108 | 109 | @property (nonatomic) TFPAbsolutePosition position; 110 | 111 | + (NSString*)nameForPrinterColor:(TFPPrinterColor)color; 112 | + (NSString*)minimumTestedFirmwareVersion; 113 | + (NSString*)maximumTestedFirmwareVersion; 114 | @end 115 | 116 | 117 | @interface TFPPrinterContext : NSObject 118 | @property (readonly) TFPPrinter *printer; 119 | 120 | - (void)sendGCode:(TFPGCode*)code responseHandler:(void(^)(BOOL success, TFPGCodeResponseDictionary value))block; 121 | - (void)runGCodeProgram:(TFPGCodeProgram*)program completionHandler:(void(^)(BOOL success, NSArray *values))completionHandler; 122 | 123 | - (void)invalidate; 124 | @end 125 | 126 | 127 | #import "TFPPrinterHelpers.h" -------------------------------------------------------------------------------- /microprint/TFPPrinterConnection.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrinterConnection.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Wed 2015-07-29. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | @class TFPGCode, ORSSerialPort; 12 | 13 | 14 | typedef NS_ENUM(NSInteger, TFPPrinterMessageType) { 15 | TFPPrinterMessageTypeInvalid, 16 | TFPPrinterMessageTypeConfirmation, // value = nil or NSDictionary 17 | TFPPrinterMessageTypeSkipNotice, // value = nil 18 | TFPPrinterMessageTypeError, // value = NSNumber for error code 19 | TFPPrinterMessageTypeResendRequest, // value = nil 20 | TFPPrinterMessageTypeTemperatureUpdate, // value = NSNumber for temperature 21 | TFPPrinterMessageTypeUnknown, // value = NSString with raw incoming line 22 | }; 23 | 24 | 25 | typedef NS_ENUM(NSUInteger, TFPPrinterConnectionState) { 26 | TFPPrinterConnectionStateDisconnected, 27 | TFPPrinterConnectionStatePending, 28 | TFPPrinterConnectionStateConnected, 29 | }; 30 | 31 | 32 | @interface TFPPrinterConnection : NSObject 33 | - (instancetype)initWithSerialPort:(ORSSerialPort*)serialPort; 34 | @property (readonly) ORSSerialPort *serialPort; 35 | 36 | - (void)openWithCompletionHandler:(void(^)(NSError *error))completionHandler; 37 | - (void)sendGCode:(TFPGCode*)code; 38 | 39 | @property (readonly) TFPPrinterConnectionState state; 40 | 41 | // Blocks are called on a private queue, remember to dispatch! 42 | @property (copy) void(^messageHandler)(TFPPrinterMessageType type, NSInteger lineNumber, id value); 43 | @property (copy) void(^rawLineHandler)(NSString *line); 44 | @end -------------------------------------------------------------------------------- /microprint/TFPPrinterHelpers.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrinterHelpers.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sun 2015-08-02. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPPrinter.h" 10 | 11 | @interface TFPPrinter (CommandHelpers) 12 | - (void)setBacklashValues:(TFPBacklashValues)values completionHandler:(void(^)(BOOL success))completionHandler; 13 | - (void)fetchPositionWithCompletionHandler:(void(^)(BOOL success, TFP3DVector *position, NSNumber *E))completionHandler; 14 | @end 15 | 16 | 17 | 18 | @interface TFPPrinterContext (CommandHelpers) 19 | - (void)setRelativeMode:(BOOL)relative completionHandler:(void(^)(BOOL success))completionHandler; 20 | - (void)moveToPosition:(TFP3DVector*)position usingFeedRate:(double)F completionHandler:(void(^)(BOOL success))completionHandler; 21 | - (void)waitForExecutionCompletionWithHandler:(void(^)())completionHandler; 22 | 23 | - (void(^)())setHeaterTemperatureAsynchronously:(double)targetTemperature progressBlock:(void(^)(double currentTemperature))progressBlock completionBlock:(void(^)())completionBlock; 24 | 25 | - (void(^)())moveAsynchronouslyToPosition:(TFP3DVector*)targetPosition feedRate:(double)feedRate progressBlock:(void(^)(double fraction, TFP3DVector *position))progressBlock completionBlock:(void(^)())completionBlock; 26 | @end -------------------------------------------------------------------------------- /microprint/TFPPrinterManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrinterManager.h 3 | // MicroPrint 4 | // 5 | // Created by Tomas Franzén on Tue 2015-06-23. 6 | // 7 | 8 | #import 9 | 10 | 11 | @interface TFPPrinterManager : NSObject 12 | 13 | + (instancetype)sharedManager; 14 | 15 | - (void)startDryRunMode; 16 | 17 | @property (readonly) NSArray *printers; // Observable 18 | @end -------------------------------------------------------------------------------- /microprint/TFPPrinterManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPPrinterManager.m 3 | // MicroPrint 4 | // 5 | // Created by Tomas Franzén on Tue 2015-06-23. 6 | // 7 | 8 | #import "TFPPrinterManager.h" 9 | #import "TFPPrinter.h" 10 | #import "TFPExtras.h" 11 | #import "TFPDryRunPrinterConnection.h" 12 | #import "TFPPrinterConnection.h" 13 | 14 | #import "MAKVONotificationCenter.h" 15 | #import "ORSSerialPortManager.h" 16 | 17 | 18 | static const uint16_t M3DMicroUSBVendorID = 0x03EB; 19 | static const uint16_t M3DMicroUSBProductID = 0x2404; 20 | 21 | 22 | @interface TFPPrinterManager () 23 | @property (readwrite) NSArray *printers; // Observable 24 | @end 25 | 26 | 27 | @implementation TFPPrinterManager 28 | 29 | 30 | + (instancetype)sharedManager { 31 | static TFPPrinterManager *singleton; 32 | return singleton ?: (singleton = [self new]); 33 | } 34 | 35 | 36 | - (void)startDryRunMode { 37 | TFPPrinter *printer = [[TFPPrinter alloc] initWithConnection:[TFPDryRunPrinterConnection new]]; 38 | [[self mutableArrayValueForKey:@"printers"] addObject:printer]; 39 | } 40 | 41 | 42 | - (NSArray*)printersForSerialPorts:(NSArray*)serialPorts { 43 | return [[serialPorts tf_selectWithBlock:^BOOL(ORSSerialPort *port) { 44 | return port.USBVendorID.unsignedShortValue == M3DMicroUSBVendorID && port.USBProductID.unsignedShortValue == M3DMicroUSBProductID; 45 | }] tf_mapWithBlock:^TFPPrinter*(ORSSerialPort *serialPort) { 46 | TFPPrinterConnection *connection = [[TFPPrinterConnection alloc] initWithSerialPort:serialPort]; 47 | return [[TFPPrinter alloc] initWithConnection:connection]; 48 | }]; 49 | } 50 | 51 | 52 | - (instancetype)init { 53 | if(!(self = [super init])) return nil; 54 | __weak __typeof__(self) weakSelf = self; 55 | 56 | self.printers = [self printersForSerialPorts:[ORSSerialPortManager sharedSerialPortManager].availablePorts]; 57 | 58 | [[ORSSerialPortManager sharedSerialPortManager] addObserver:self keyPath:@"availablePorts" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld block:^(MAKVONotification *notification) { 59 | NSMutableArray *printers = [weakSelf mutableArrayValueForKey:@"printers"]; 60 | 61 | if(notification.kind == NSKeyValueChangeRemoval) { 62 | NSArray *removedPrinters = [weakSelf.printers tf_selectWithBlock:^BOOL(TFPPrinter *printer) { 63 | return [printer printerShouldBeInvalidatedWithRemovedSerialPorts:notification.oldValue]; 64 | }]; 65 | [printers removeObjectsInArray:removedPrinters]; 66 | 67 | }else{ 68 | NSArray *existingPorts = [self.printers valueForKeyPath:@"connection.serialPort"]; 69 | NSArray *newSerialPorts = [notification.newValue tf_rejectWithBlock:^BOOL(id object) { 70 | return [existingPorts containsObject:object]; 71 | }]; 72 | 73 | dispatch_after(dispatch_time(0, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 74 | [printers addObjectsFromArray:[weakSelf printersForSerialPorts:newSerialPorts]]; 75 | }); 76 | } 77 | }]; 78 | 79 | return self; 80 | } 81 | 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /microprint/TFPRaiseHeadOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPRaiseHeadOperation.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sun 2015-06-28. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "TFPOperation.h" 11 | 12 | @interface TFPRaiseHeadOperation : TFPOperation 13 | @property double targetHeight; 14 | 15 | @property (copy) void(^didStartBlock)(); 16 | @property (copy) void(^didStopBlock)(BOOL didRaise); 17 | @end -------------------------------------------------------------------------------- /microprint/TFPRaiseHeadOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPRaiseHeadOperation.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Sun 2015-06-28. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPRaiseHeadOperation.h" 10 | #import "TFPExtras.h" 11 | #import "TFPGCodeHelpers.h" 12 | #import "TFP3DVector.h" 13 | 14 | 15 | @interface TFPRaiseHeadOperation () 16 | @property BOOL stopped; 17 | @property (readwrite) TFPOperationStage stage; 18 | @end 19 | 20 | 21 | static const double raiseStep = 0.1; 22 | 23 | 24 | @implementation TFPRaiseHeadOperation 25 | @synthesize stage=_stage; 26 | 27 | 28 | - (void)raiseStepFromZ:(double)Z toLevel:(double)targetHeight completionHandler:(void(^)())completionHandler { 29 | if(self.stopped || Z >= targetHeight) { 30 | completionHandler(); 31 | return; 32 | } 33 | 34 | Z += raiseStep; 35 | 36 | TFP3DVector *position = [TFP3DVector zVector:Z]; 37 | [self.context moveToPosition:position usingFeedRate:2900 completionHandler:^(BOOL success) { 38 | [self raiseStepFromZ:Z toLevel:targetHeight completionHandler:completionHandler]; 39 | }]; 40 | } 41 | 42 | 43 | - (BOOL)start { 44 | if(![super start]) { 45 | return NO; 46 | } 47 | 48 | double targetHeight = self.targetHeight; 49 | self.stage = TFPOperationStagePreparation; 50 | 51 | [self.printer fetchPositionWithCompletionHandler:^(BOOL success, TFP3DVector *position, NSNumber *E) { 52 | [self.context setRelativeMode:NO completionHandler:^(BOOL success) { 53 | double Z = position.z.doubleValue; 54 | 55 | if(Z < targetHeight) { 56 | if(self.didStartBlock) { 57 | self.didStartBlock(); 58 | } 59 | self.stage = TFPOperationStageRunning; 60 | 61 | [self raiseStepFromZ:Z toLevel:targetHeight completionHandler:^{ 62 | self.stage = TFPOperationStageEnding; 63 | 64 | [self.printer sendGCode:[TFPGCode turnOffMotorsCode] responseHandler:^(BOOL success, NSDictionary *value) { 65 | if(self.didStopBlock) { 66 | self.didStopBlock(YES); 67 | } 68 | [self ended]; 69 | }]; 70 | }]; 71 | }else{ 72 | if(self.didStopBlock) { 73 | self.didStopBlock(NO); 74 | } 75 | [self ended]; 76 | } 77 | }]; 78 | }]; 79 | 80 | return YES; 81 | } 82 | 83 | 84 | - (void)stop { 85 | [super stop]; 86 | self.stopped = YES; 87 | } 88 | 89 | 90 | - (TFPOperationKind)kind { 91 | return TFPOperationKindUtility; 92 | } 93 | 94 | 95 | - (NSString *)activityDescription { 96 | return @"Raising Print Head"; 97 | } 98 | 99 | 100 | @end -------------------------------------------------------------------------------- /microprint/TFPSlicerProfile.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPSlicerProfile.h 3 | // microprint 4 | // 5 | // Created by William Waggoner on 9/13/15. 6 | // Copyright © 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TFPGCode.h" 11 | #import "TFPExtras.h" 12 | #import "TFPGCodeHelpers.h" 13 | 14 | typedef NS_ENUM (NSInteger, SlicerProfileType) { 15 | CuraProfile, 16 | Slic3rProfile, 17 | S3dProfile, 18 | }; 19 | 20 | @interface TFPSlicerProfile : NSObject 21 | @property SlicerProfileType profileType; 22 | - (instancetype)initFromLines: (NSArray *)lines; 23 | - (void)setValue:(id)value forUndefinedKey:(NSString *)key; 24 | - (id)objectForKeyedSubscript:(id)key; 25 | - (id)valueForUndefinedKey:(NSString *)key; 26 | - (BOOL)loadCuraProfile:(NSArray *)lines; 27 | - (BOOL)loadSlic3rProfile:(NSArray *)lines; 28 | - (NSString *)formattedValueForKey:(NSString *)key; 29 | @end 30 | -------------------------------------------------------------------------------- /microprint/TFPStopwatch.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPStopwatch.h 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Mon 2015-08-10. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TFPStopwatch : NSObject 12 | - (void)start; 13 | - (void)stop; 14 | - (void)reset; 15 | 16 | @property (readonly) NSTimeInterval elapsedTime; 17 | @end 18 | -------------------------------------------------------------------------------- /microprint/TFPStopwatch.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPStopwatch.m 3 | // microprint 4 | // 5 | // Created by Tomas Franzén on Mon 2015-08-10. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPStopwatch.h" 10 | #import "TFPExtras.h" 11 | #import "TFTimer.h" 12 | 13 | 14 | @interface TFPStopwatch () 15 | @property NSTimeInterval storedTime; 16 | @property uint64_t startTime; 17 | 18 | @property TFTimer *updateTimer; 19 | @end 20 | 21 | 22 | @implementation TFPStopwatch 23 | 24 | 25 | - (void)start { 26 | __weak __typeof__(self) weakSelf = self; 27 | 28 | self.startTime = TFNanosecondTime(); 29 | self.updateTimer = [TFTimer timerWithInterval:1 repeating:YES block:^{ 30 | [weakSelf willChangeValueForKey:@"elapsedTime"]; 31 | [weakSelf didChangeValueForKey:@"elapsedTime"]; 32 | }]; 33 | } 34 | 35 | 36 | - (void)stop { 37 | self.storedTime = self.elapsedTime; 38 | self.startTime = 0; 39 | self.updateTimer = nil; 40 | } 41 | 42 | 43 | - (void)reset { 44 | [self stop]; 45 | self.storedTime = 0; 46 | } 47 | 48 | 49 | - (NSTimeInterval)elapsedTime { 50 | double duration = self.storedTime; 51 | if(self.startTime > 0) { 52 | duration += ((double)(TFNanosecondTime() - self.startTime)) / NSEC_PER_SEC; 53 | } 54 | return duration; 55 | } 56 | 57 | 58 | @end -------------------------------------------------------------------------------- /microprint/TFPZeroBedOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFPZeroBedOperation.h 3 | // microprint 4 | // 5 | // Created by William Waggoner on 7/29/15. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPOperation.h" 10 | 11 | @interface TFPZeroBedOperation : TFPOperation 12 | @property (copy) void(^progressFeedback)(NSString *msg); 13 | @property (copy) void(^didStopBlock)(BOOL completed); 14 | @end 15 | -------------------------------------------------------------------------------- /microprint/TFPZeroBedOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFPZeroBedOperation.m 3 | // microprint 4 | // 5 | // Created by William Waggoner on 7/29/15. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFPZeroBedOperation.h" 10 | #import "TFPExtras.h" 11 | #import "TFPGCodeHelpers.h" 12 | #import "TFP3DVector.h" 13 | 14 | 15 | @interface TFPZeroBedOperation () 16 | @property BOOL stopped; 17 | @property (readwrite) TFPOperationStage stage; 18 | @end 19 | 20 | 21 | 22 | @implementation TFPZeroBedOperation 23 | @synthesize stage=_stage; 24 | 25 | 26 | - (BOOL)start { 27 | if(![super start]) { 28 | return NO; 29 | } 30 | 31 | const double temperature = 150; // Warm it up a bit 32 | const double moveFeedRate = 2900; 33 | 34 | TFP3DVector *parkingLocation = [TFP3DVector vectorWithX:nil Y:@90 Z:@10]; 35 | 36 | 37 | TFPGCodeProgram *prep = [TFPGCodeProgram programWithLines:@[ 38 | [TFPGCode codeForHeaterTemperature:temperature waitUntilDone:YES], 39 | [TFPGCode codeForTurningOffHeater], 40 | [TFPGCode turnOffFanCode], 41 | ]]; 42 | 43 | TFPGCodeProgram *park = [TFPGCodeProgram programWithLines:@[ 44 | [TFPGCode absoluteModeCode], 45 | [TFPGCode moveWithPosition:parkingLocation feedRate:moveFeedRate], 46 | [TFPGCode waitForCompletionCode], 47 | ]]; 48 | 49 | if(self.progressFeedback) { 50 | self.progressFeedback(@"Heating up…"); 51 | } 52 | 53 | self.stage = TFPOperationStagePreparation; 54 | 55 | [self.context runGCodeProgram:prep completionHandler:^(BOOL success, NSArray *valueDictionaries) { 56 | if (self.stopped) { 57 | [self doStopCompleted:NO]; 58 | 59 | }else{ 60 | if(self.progressFeedback) { 61 | self.progressFeedback(@"Finding Bed Location…"); 62 | } 63 | 64 | self.stage = TFPOperationStageRunning; 65 | [self.context sendGCode:[TFPGCode findZeroCode] responseHandler:^(BOOL success, TFPGCodeResponseDictionary value) { 66 | self.stage = TFPOperationStageEnding; 67 | if (self.stopped) { 68 | [self doStopCompleted:NO]; 69 | 70 | }else{ 71 | if(self.progressFeedback) { 72 | self.progressFeedback(@"Parking Print Head…"); 73 | } 74 | 75 | [self.context runGCodeProgram:park completionHandler:^(BOOL success, NSArray *valueDictionaries) { 76 | [self doStopCompleted:YES]; 77 | }]; 78 | } 79 | }]; 80 | } 81 | }]; 82 | 83 | return YES; 84 | } 85 | 86 | 87 | - (void)stop { 88 | [super stop]; 89 | self.stopped = YES; 90 | if(self.progressFeedback) { 91 | self.progressFeedback(@"Stopping..."); 92 | } 93 | } 94 | 95 | 96 | - (NSString *)activityDescription { 97 | return @"Calibrating bed location"; 98 | } 99 | 100 | 101 | - (void)doStopCompleted:(BOOL)completed { 102 | [self ended]; 103 | if(self.didStopBlock) { 104 | self.didStopBlock(completed); 105 | } 106 | } 107 | 108 | 109 | - (TFPOperationKind)kind { 110 | return TFPOperationKindCalibration; 111 | } 112 | 113 | 114 | @end -------------------------------------------------------------------------------- /microprint/TFStringScanner.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | typedef enum { 4 | TFTokenTypeIdentifier, 5 | TFTokenTypeNumeric, 6 | TFTokenTypeSymbol, 7 | } TFTokenType; 8 | 9 | 10 | @interface TFStringScanner : NSObject 11 | 12 | @property (readonly, copy, nonatomic) NSString *string; 13 | @property (nonatomic) NSUInteger location; 14 | @property (readonly, getter=isAtEnd, nonatomic) BOOL atEnd; 15 | @property (readonly, nonatomic) TFTokenType lastTokenType; 16 | 17 | + (id)scannerWithString:(NSString*)string; 18 | - (id)initWithString:(NSString*)string; 19 | 20 | - (void)addMulticharacterSymbol:(NSString*)symbol; 21 | - (void)addMulticharacterSymbols:(NSString*)symbol, ...; 22 | - (void)removeMulticharacterSymbol:(NSString*)symbol; 23 | 24 | - (unichar)scanCharacter; 25 | - (NSString*)scanForLength:(NSUInteger)length; 26 | - (NSString*)scanStringFromCharacterSet:(NSCharacterSet*)set; 27 | 28 | - (BOOL)scanString:(NSString*)substring; 29 | - (NSString*)scanToString:(NSString*)substring; 30 | - (BOOL)scanWhitespace; 31 | - (NSString*)scanToEnd; 32 | 33 | - (NSString*)scanToken; 34 | - (BOOL)scanToken:(NSString*)matchToken; 35 | - (NSString*)peekToken; 36 | 37 | @end -------------------------------------------------------------------------------- /microprint/TFTimer.h: -------------------------------------------------------------------------------- 1 | // 2 | // TFTimer.h 3 | // Tåg 4 | // 5 | // Created by Tomas Franzén on sön 2015-03-29. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TFTimer : NSObject 12 | + (instancetype)timerWithInterval:(NSTimeInterval)interval repeating:(BOOL)repeat block:(void(^)())action; 13 | - (void)invalidate; 14 | @end -------------------------------------------------------------------------------- /microprint/TFTimer.m: -------------------------------------------------------------------------------- 1 | // 2 | // TFTimer.m 3 | // Tåg 4 | // 5 | // Created by Tomas Franzén on sön 2015-03-29. 6 | // Copyright (c) 2015 Tomas Franzén. All rights reserved. 7 | // 8 | 9 | #import "TFTimer.h" 10 | 11 | @interface TFTimer () 12 | @property (weak) NSTimer *timer; 13 | @end 14 | 15 | 16 | 17 | @implementation NSObject (TFTimerBlockInvocation) 18 | 19 | - (void)tftimer_invoke { 20 | ((void(^)())self)(); 21 | } 22 | 23 | @end 24 | 25 | 26 | 27 | @implementation TFTimer 28 | 29 | 30 | - (instancetype)initWithInterval:(NSTimeInterval)interval repeating:(BOOL)repeat block:(void(^)())action { 31 | if(!(self = [super init])) return nil; 32 | 33 | action = [action copy]; 34 | self.timer = [NSTimer scheduledTimerWithTimeInterval:interval target:action selector:@selector(tftimer_invoke) userInfo:nil repeats:repeat]; 35 | 36 | return self; 37 | } 38 | 39 | 40 | + (instancetype)timerWithInterval:(NSTimeInterval)interval repeating:(BOOL)repeat block:(void(^)())action { 41 | return [[self alloc] initWithInterval:interval repeating:repeat block:action]; 42 | } 43 | 44 | 45 | - (void)dealloc { 46 | [self invalidate]; 47 | } 48 | 49 | 50 | - (void)invalidate { 51 | [self.timer invalidate]; 52 | self.timer = nil; 53 | } 54 | 55 | 56 | @end --------------------------------------------------------------------------------