diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..e2b9d50 Binary files /dev/null and b/.DS_Store differ diff --git a/MTMR.xcodeproj/project.pbxproj b/MTMR.xcodeproj/project.pbxproj index bd54938..2958cd6 100644 --- a/MTMR.xcodeproj/project.pbxproj +++ b/MTMR.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 6042B6A72083E03A00C525C8 /* AppScrubberTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */; }; 6042B6AA2083E27000C525C8 /* DeprecatedCarbonAPI.c in Sources */ = {isa = PBXBuildFile; fileRef = 6042B6A92083E27000C525C8 /* DeprecatedCarbonAPI.c */; }; B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0008E542080286C003AD4DD /* SupportHelpers.swift */; }; + B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = B05600D22083E9BB00EB218D /* CustomSlider.swift */; }; B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D621205E03F5006E6B86 /* TouchBarController.swift */; }; B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */; }; B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B059D62C205F11E8006E6B86 /* DFRFoundation.framework */; }; @@ -66,6 +67,7 @@ 6042B6A82083E1F500C525C8 /* DeprecatedCarbonAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeprecatedCarbonAPI.h; sourceTree = ""; }; 6042B6A92083E27000C525C8 /* DeprecatedCarbonAPI.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = DeprecatedCarbonAPI.c; sourceTree = ""; }; B0008E542080286C003AD4DD /* SupportHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportHelpers.swift; sourceTree = ""; }; + B05600D22083E9BB00EB218D /* CustomSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomSlider.swift; sourceTree = ""; }; B059D621205E03F5006E6B86 /* TouchBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchBarController.swift; sourceTree = ""; }; B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomButtonTouchBarItem.swift; sourceTree = ""; }; B059D629205E13E5006E6B86 /* TouchBarPrivateApi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TouchBarPrivateApi.h; sourceTree = ""; }; @@ -169,6 +171,7 @@ 6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */, 368EDDE620812A1D00E10953 /* ScrollViewItem.swift */, 6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */, + B05600D22083E9BB00EB218D /* CustomSlider.swift */, ); path = MTMR; sourceTree = ""; @@ -329,6 +332,7 @@ buildActionMask = 2147483647; files = ( B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */, + B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */, 36C2ECD9207B74B4003CDA33 /* AppleScriptTouchBarItem.swift in Sources */, B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */, B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */, diff --git a/MTMR/AppDelegate.swift b/MTMR/AppDelegate.swift index e5e7926..c2ded9b 100644 --- a/MTMR/AppDelegate.swift +++ b/MTMR/AppDelegate.swift @@ -26,7 +26,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { // Insert code here to tear down your application } - @objc func testFn(_ sender: Any?) { + @objc func openPrefereces(_ sender: Any?) { let task = Process() let appSupportDirectory = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!.appending("/MTMR") let presetPath = appSupportDirectory.appending("/items.json") @@ -35,9 +35,14 @@ class AppDelegate: NSObject, NSApplicationDelegate { task.launch() } + @objc func updatePreset(_ sender: Any?) { + TouchBarController.shared.createAndUpdatePreset() + } + func createMenu() { let menu = NSMenu() - menu.addItem(withTitle: "Preferences", action: #selector(testFn(_:)), keyEquivalent: ",") + menu.addItem(withTitle: "Preferences", action: #selector(openPrefereces(_:)), keyEquivalent: ",") + menu.addItem(withTitle: "Reload Preset", action: #selector(updatePreset(_:)), keyEquivalent: "r") menu.addItem(NSMenuItem.separator()) menu.addItem(withTitle: "Quit", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q") statusItem.menu = menu diff --git a/MTMR/BrightnessViewController.swift b/MTMR/BrightnessViewController.swift index fb6bc27..3206c0c 100644 --- a/MTMR/BrightnessViewController.swift +++ b/MTMR/BrightnessViewController.swift @@ -9,7 +9,11 @@ class BrightnessViewController: NSCustomTouchBarItem { init(identifier: NSTouchBarItem.Identifier, refreshInterval: Double, image: NSImage? = nil) { super.init(identifier: identifier) - sliderItem = CustomSlider(knob: image!) + if (image == nil) { + sliderItem = CustomSlider() + } else { + sliderItem = CustomSlider(knob: image!) + } sliderItem.target = self sliderItem.action = #selector(BrightnessViewController.sliderValueChanged(_:)) sliderItem.minValue = 0.0 diff --git a/MTMR/CustomButtonTouchBarItem.swift b/MTMR/CustomButtonTouchBarItem.swift index 7b969e7..d40c966 100644 --- a/MTMR/CustomButtonTouchBarItem.swift +++ b/MTMR/CustomButtonTouchBarItem.swift @@ -17,9 +17,10 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem { super.init(identifier: identifier) button = NSButton(title: title, target: self, action: #selector(didTapped)) button.font = .systemFont(ofSize: CGFloat(13.0)) + button.title = title self.view = button } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } diff --git a/MTMR/CustomSlider.swift b/MTMR/CustomSlider.swift new file mode 100644 index 0000000..81aea36 --- /dev/null +++ b/MTMR/CustomSlider.swift @@ -0,0 +1,108 @@ +// +// CustomSlider.swift +// MTMR +// +// Created by Anton Palgunov on 15/04/2018. +// Copyright © 2018 Anton Palgunov. All rights reserved. +// + +import Foundation + +class CustomSliderCell: NSSliderCell { + var knobImage:NSImage! + private var _currentKnobRect:NSRect! + private var _barRect:NSRect! + + required init(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + override init() { + super.init() + } + + init(knob:NSImage?) { + knobImage = knob; + super.init() + } + + override func drawKnob(_ knobRect: NSRect) { + if (knobImage == nil) { + super.drawKnob(knobRect) + return; + } + + _currentKnobRect = knobRect; + drawBar(inside: _barRect, flipped: true) + + let x = (knobRect.origin.x * (_barRect.size.width - (knobImage.size.width - knobRect.size.width)) / _barRect.size.width)+1; + let y = knobRect.origin.y+3 + + knobImage.draw( + at: NSPoint(x: x, y: y), + from: NSZeroRect, + operation: NSCompositingOperation.sourceOver, + fraction: 1 + ) + } + + override func drawBar(inside aRect: NSRect, flipped: Bool) { + _barRect = aRect + + var rect = aRect + rect.size.height = CGFloat(4) + let barRadius = CGFloat(2) + let value = CGFloat((self.doubleValue - self.minValue) / (self.maxValue - self.minValue)) + let finalWidth = CGFloat(value * (self.controlView!.frame.size.width - 12)) + + var leftRect = rect + leftRect.size.width = finalWidth + let bg = NSBezierPath(roundedRect: rect, xRadius: barRadius, yRadius: barRadius) + NSColor.lightGray.setFill() + bg.fill() + + let active = NSBezierPath(roundedRect: leftRect, xRadius: barRadius, yRadius: barRadius) + NSColor.darkGray.setFill() + active.fill() + } +} + +class CustomSlider:NSSlider { + + var currentValue:CGFloat = 0 + + override func setNeedsDisplay(_ invalidRect: NSRect) { + super.setNeedsDisplay(invalidRect) + } + + override func awakeFromNib() { + super.awakeFromNib() + if ((self.cell?.isKind(of: CustomSliderCell.self)) == false) { + let cell:CustomSliderCell = CustomSliderCell() + self.cell = cell + } + } + + convenience init(knob:NSImage) { + self.init() + self.cell = CustomSliderCell(knob: knob) + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + } + + func knobImage() -> NSImage { + let cell = self.cell as! CustomSliderCell + return cell.knobImage + } + + func setKnobImage(image:NSImage) { + let cell = self.cell as! CustomSliderCell + cell.knobImage = image + } +} diff --git a/MTMR/Info.plist b/MTMR/Info.plist index 0c5dce7..f0fae0d 100644 --- a/MTMR/Info.plist +++ b/MTMR/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.8 + 0.8.1 CFBundleVersion 1 LSMinimumSystemVersion diff --git a/MTMR/SupportHelpers.swift b/MTMR/SupportHelpers.swift index 76ba761..610165b 100644 --- a/MTMR/SupportHelpers.swift +++ b/MTMR/SupportHelpers.swift @@ -49,4 +49,35 @@ extension NSImage { // Return the new image return imageWithNewSize } + + func rotateByDegreess(degrees:CGFloat) -> NSImage { + + var imageBounds = NSZeroRect ; imageBounds.size = self.size + let pathBounds = NSBezierPath(rect: imageBounds) + var transform = NSAffineTransform() + transform.rotate(byDegrees: degrees) + pathBounds.transform(using: transform as AffineTransform) + let rotatedBounds:NSRect = NSMakeRect(NSZeroPoint.x, NSZeroPoint.y , self.size.width, self.size.height ) + let rotatedImage = NSImage(size: rotatedBounds.size) + + //Center the image within the rotated bounds + imageBounds.origin.x = NSMidX(rotatedBounds) - (NSWidth(imageBounds) / 2) + imageBounds.origin.y = NSMidY(rotatedBounds) - (NSHeight(imageBounds) / 2) + + // Start a new transform + transform = NSAffineTransform() + // Move coordinate system to the center (since we want to rotate around the center) + transform.translateX(by: +(NSWidth(rotatedBounds) / 2 ), yBy: +(NSHeight(rotatedBounds) / 2)) + transform.rotate(byDegrees: degrees) + // Move the coordinate system bak to normal + transform.translateX(by: -(NSWidth(rotatedBounds) / 2 ), yBy: -(NSHeight(rotatedBounds) / 2)) + // Draw the original image, rotated, into the new image + rotatedImage.lockFocus() + transform.concat() + self.draw(in: imageBounds, from: NSZeroRect, operation: NSCompositingOperation.copy, fraction: 1.0) + rotatedImage.unlockFocus() + + return rotatedImage + } + } diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift index adee8b6..ada3da1 100644 --- a/MTMR/TouchBarController.swift +++ b/MTMR/TouchBarController.swift @@ -57,12 +57,22 @@ class TouchBarController: NSObject, NSTouchBarDelegate { self?.dismissTouchBar() })) + createAndUpdatePreset() + } + + func createAndUpdatePreset() { + self.itemDefinitions = [:] + self.items = [:] + self.leftIdentifiers = [] + self.centerItems = [] + self.rightIdentifiers = [] + loadItemDefinitions() createItems() centerItems = self.itemDefinitions.compactMap { (identifier, definition) -> NSTouchBarItem? in return definition.align == .center ? items[identifier] : nil } - + touchBar.delegate = self touchBar.defaultItemIdentifiers = self.leftIdentifiers + [.centerScrollArea] + self.rightIdentifiers self.presentTouchBar() diff --git a/MTMR/VolumeViewController.swift b/MTMR/VolumeViewController.swift index 30ab919..3ca4615 100644 --- a/MTMR/VolumeViewController.swift +++ b/MTMR/VolumeViewController.swift @@ -18,7 +18,11 @@ class VolumeViewController: NSCustomTouchBarItem { onAudioObjectID: defaultDeviceID, forPropertyAddress: &forPropertyAddress) - sliderItem = CustomSlider(knob: image!) + if (image == nil) { + sliderItem = CustomSlider() + } else { + sliderItem = CustomSlider(knob: image!) + } sliderItem.target = self sliderItem.action = #selector(VolumeViewController.sliderValueChanged(_:)) sliderItem.minValue = 0.0 @@ -116,96 +120,3 @@ class VolumeViewController: NSCustomTouchBarItem { } } -class CustomSliderCell: NSSliderCell { - var knobImage:NSImage! - private var _currentKnobRect:NSRect! - private var _barRect:NSRect! - - required init(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } - - override init() { - super.init() - } - - init(knob:NSImage) { - knobImage = knob; - super.init() - } - - override func drawKnob(_ knobRect: NSRect) { - - if (knobImage == nil) { - super.drawKnob(knobRect) - return; - } - - _currentKnobRect = knobRect; - drawBar(inside: _barRect, flipped: false) - - let newOriginX:CGFloat = knobRect.origin.x * - (_barRect.size.width - (knobImage.size.width - knobRect.size.width)) / _barRect.size.width; - - knobImage.draw(at: NSPoint(x: newOriginX, y: knobRect.origin.y+3), from: NSRect(x: 0, y: 0, width: knobImage.size.width, height: knobImage.size.height), operation: NSCompositingOperation.sourceOver, fraction: 1) - } - - override func drawBar(inside aRect: NSRect, flipped: Bool) { - _barRect = aRect - - var rect = aRect - rect.size.height = CGFloat(3) - let barRadius = CGFloat(3) - let value = CGFloat((self.doubleValue - self.minValue) / (self.maxValue - self.minValue)) - let finalWidth = CGFloat(value * (self.controlView!.frame.size.width - 12)) - - var leftRect = rect - leftRect.size.width = finalWidth - let bg = NSBezierPath(roundedRect: rect, xRadius: barRadius, yRadius: barRadius) - NSColor.lightGray.setFill() - bg.fill() - let active = NSBezierPath(roundedRect: leftRect, xRadius: barRadius, yRadius: barRadius) - NSColor.darkGray.setFill() - active.fill() - } -} - -class CustomSlider:NSSlider { - - var currentValue:CGFloat = 0 - - override func setNeedsDisplay(_ invalidRect: NSRect) { - super.setNeedsDisplay(invalidRect) - } - - override func awakeFromNib() { - super.awakeFromNib() - if ((self.cell?.isKind(of: CustomSliderCell.self)) == false) { - let cell:CustomSliderCell = CustomSliderCell() - self.cell = cell - } - } - - convenience init(knob:NSImage) { - self.init() - self.cell = CustomSliderCell(knob: knob) - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - override init(frame frameRect: NSRect) { - super.init(frame: frameRect) - } - - func knobImage() -> NSImage { - let cell = self.cell as! CustomSliderCell - return cell.knobImage - } - - func setKnobImage(image:NSImage) { - let cell = self.cell as! CustomSliderCell - cell.knobImage = image - } -} diff --git a/MTMR/defaultPreset.json b/MTMR/defaultPreset.json index aabb851..cac4fa2 100644 --- a/MTMR/defaultPreset.json +++ b/MTMR/defaultPreset.json @@ -1,23 +1,76 @@ [ - { "type": "escape" }, - { "type": "exitTouchbar" }, - { "type": "volume", "width": 80 }, - { "type": "brightness", "width": 80 }, - { "type": "brightnessDown" }, + { "type": "escape", "align": "left" }, + { "type": "exitTouchbar", "width": 44, "align": "left" }, + { "type": "brightnessDown", "width": 44, "align": "left" }, { - "type": "staticButton", - "title": "🔆", - "action": "keyPress", - "keycode": 113, - "width": 36, + "type": "brightness", + "width": 60, + "align": "left", + "image": { + "base64": + "iVBORw0KGgoAAAANSUhEUgAAAIAAAACAAQMAAAD58POIAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAGUExURffLOPfLNyaSVzUAAAACdFJOU/kBxOqnWgAAAbJJREFUSMfVljtyhDAQBVulQCFH4CgcDR1NR9ERFBKoeA5GfGddtkNvwFINFKP5tED22+Zxwviv6QVKfIEc/iNoF5gkpLIeYI8SUp4PsAUJiekADQntF6isQjvxCTrhAJlFqMMBeIH9BMsD7DAb2BhvYbIyNAOCZIWqYKGTpDZJFQu9EKVd44RxQRq3IrULWD62C8wSssWUZEsR0k6wcDOrJZmoBpMKI+s5qkBQCQOUJADVOECdOsDS0gDbsgHMfT4rVwHSrZQFIN5ABka8BgDgAeZ+BztBgvUEnSgVlhNsTFJjvoF5HAZorBpdYKAiSRbqNyBIUr6AjZMdPwO72R40MElS+wZUWA+wQ6LAYkFvdIhkmA+wQSDDdIAGAZ6A34H0x0fca11gBZZsIHSIfnE/5+NjCn/OuiuUB+/aunZwDeNayjXdTpDN0wlY+r1PfWu75nfj8RogN2JuCN2Y5qgMwTI0wGPUnQw6Qarx0sVNKA5Mn6VUL22lIbZoYitDbPmlvocc9Umfl2D7adz1reC3pF8av4m+DCenp/ndZuG3E7fhuC3pH2+vnz8V3MfE+bnxBTXuuIMTrLWHAAAAAElFTkSuQmCC" + } }, - { "type": "volumeDown", "width": 44 }, - { "type": "volumeUp", "width": 44 }, - { "type": "previous" }, - { "type": "play" }, - { "type": "next" }, + { "type": "brightnessUp", "width": 44, "align": "left" }, + { + "type": "appleScriptTitledButton", + "source": { + "inline": + "if application \"iTunes\" is running then\rtell application \"iTunes\"\rif player state is playing then\rreturn (get artist of current track) & \" – \" & (get name of current track)\relse\rreturn \"\"\rend if\rend tell\rend if\rreturn \"\"\r" + }, + "action": "appleScript", + "actionAppleScript": { + "inline": + "if application \"iTunes\" is running then\rtell application \"iTunes\"\rif player state is playing then\rnext track\rend if\rend tell\rend if\r" + }, + "refreshInterval": 1, + "image": { + "base64": + "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" + } + }, + { + "type": "appleScriptTitledButton", + "source": { + "inline": + "if application \"Spotify\" is running then\rtell application \"Spotify\"\rif player state is playing then\rreturn (get artist of current track) & \" – \" & (get name of current track)\relse\rreturn \"\"\rend if\rend tell\rend if\rreturn \"\"\r" + }, + "action": "appleScript", + "actionAppleScript": { + "inline": + "if application \"Spotify\" is running then\rtell application \"Spotify\"\rif player state is playing then\rnext track\rend if\rend tell\rend if\r" + }, + "refreshInterval": 1, + "image": { + "base64": + "iVBORw0KGgoAAAANSUhEUgAAAEAAAABABAMAAABYR2ztAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAYUExURUdwTB3WXx3UXh3VXx7XYBkXFRpVLRyURmIaeAQAAAAEdFJOUwDDO3fSqUUkAAABbklEQVRIx61VbW6DMAztoAeYNA7ApB6gkzhAWS24wIAL0HABaK6/pHFNEhy8TXu/kPzkPD/8cTj8K7KPAqB+K5NhQPCUrABCXe7HOUYYZxgVRLiG8RfY4DUgFFtC7cffAfZTFBwBdhWEKfgEq4ocEjgj4ZQifO6/QG9kkETp1dDeVWfRKx3XYSW0LoqY5kCElXDrQkyeCCuh6WL0M4nIWQIyzqixdfKU1koFDKvyCA8NJMzU4xiD+b4kfHRpsIyKc6hBwjVptFHVY51EMAINNDFGJITKDNQcdpX74Hz0CQ3rY5qwMp4EIxrlafzrsYZ2Veb0DkRgfNCUok4Y1fqEijfyi2b8RE9beWqa48Y/uvCNMcH9btfUi+/CGLR1vhL6Zz9N/vBlaCU+7lwY/cmJ67Ryen/2tj23PLqJBodZH8vgj544vOL4pxfI5acrSFxi8hrkU9TSKr78ZpnL50A8KPJJEo+afBblwyqf5j/iGys5j6ScrST2AAAAAElFTkSuQmCC" + } + }, + { + "type": "appleScriptTitledButton", + "source": { + "inline": + "if application \"VOX\" is running then\rtell application \"VOX\"\rif player state is 1 then\rreturn (get artist) & \" – \" & (get track)\relse\rreturn \"\"\rend if\rend tell\rend if\rreturn \"\"\r" + }, + "action": "appleScript", + "actionAppleScript": { + "inline": + "if application \"VOX\" is running then\rtell application \"VOX\"\rif player state is 1 then\rnext\rend if\rend tell\rend if\r" + }, + "refreshInterval": 1, + "image": { + "base64": + "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAADAUExURUdwTHd7gqeqtKClrd/k7n+Di7e7xI6TnNHX4cPI0Xp9hJibpOfs9u/1/vX7/rq/yZiborK3wEpOUxgYFlFXYiIhHycpLD9ESjI0NgsLCj09O4SKk19lcbBkALhoAHJ3gT8rAzMvJJugqKhcAL5xAOSxB4I/AJ5SAGpweXuAiZJJAG8zAeXr9WNiYM+NANqeAMd9APHACfr9/e7JPrO5w6mrsA4bKC0gCHhtTyAYBFcpAZduKK2JP/fost/Eb5SUlFFfi9AAAAASdFJOUwDJE9FgWjb+/vyHppTXtbn9mDupvZ0AAAdoSURBVFjDlZcLQ6O6FoWrtgI+Owl5EGgp2DrEgnV6wD4c7f//V3ftAE7nzOj17NGxpayPtXfSZGcw+CjOh1c3N9eIm5ur4fngv8Xp8KZE+F2U5bq8GZ5+WU5qP6jzsRdTeF7e1AEoN8Ovya/LMsg9mxZJErpIksJarwnK8nr4FblfQ52EDOH0zL1KUuvVfnn9eTVOryCPoVZQuGj/FOApMAhx9Uktzq/L2ksT3FuQhIVVVVRVRa+SogA1KbzgExPD0s/xdBOmKdOqODR95IdEaZba0LAkbfzyg0rA/pgekxZKV4cmtxXTEmFUEufNodIKYJjLkcbf9UEM90mqZJU3qeJRxDkXAv/hlbJNXkmVJjCBNP5CGPq1TZSyiWB5XomIi+woRBSJKj8YUVgFQ4E//FMfQM8s40VTyIhDpLVRNIJKaWLwSNqm4mEMl/YPwrkP/9AbER+UkxtWbbcvLrbbkBlCcDa23BABHn4bi1PSM2a1PFgZwbwJty+TybSLyeRlyxQlIuNY6FgpDKd/PB+uXP2tFHEheCtvhW3Q65dtiEyQRixMrBjG4uo4gTpNFApvU9Kr6sWp77qY3BFj8lLBBJdpykOLwaqPkgioAEnFi1RCz7Z3uJ2U37sgCBB3W5ZJLm0VJQmVIXgfgSAvQpYK1ACDx7bTOT2dlA8uWsYEl0EQ3KDUKcOECvqRCGgGpApXf9M/PNx3QQwyMZ9uGWZWiGelsFAHvQFUMEx4WAku2HZC+k6+vF/ip0U4wmSrBJcFZgss9xZuYYAlWhaGC1PhMb1++R6EaAl3lRFcFUI5C7duDlAFwpCzSogsfCH93fdWvm+jRYCASs5fwkyIinGsVrBAc2FYxwVLlKhgQG3n8+kv/WwjhNhsZvveQ5+EqrhKWOHVlMNtgyUkhHkpdPjy1CZA+pl4bkOIfWcBQ/EEC1xWWmKxsi6HussA9WUwQBV0BmbPz3y32+x2nD8/z/okpvM5LAjGeEg51JiFtQeAEqHhWUIGJq0B0m9mLjYdgSxMnQVhGHIIkcP5YNjEAGjJJDfF5AnzzRnY/9K3hP3SjSUAk0oLzaQOwyJGEb41FgWVuOIymHYZCKfPGFaxzBHEcQ5cYrXD3LHNt8E3WkdDbpBY8vMdMHsW0Jui9v26MCDAggNMAfgZoghGdIDbPMXewY0RWfHzqQMsN2QgC/MAkVcZWZi1DuYAJJlQBlVM0vx2cDZOw4QAPEt/AcTzDgkkh3w8Hh8SPZvtKIc2haefKapo2mE4G5x5nQOuLQA0jwggCcAqF1SFnZQEwEwCwGZ0P+sAXQqa69gBJvgeLCUBhMS6arSWogV0NWwB2gHG5KAggDYO0OXQATghJP4QIPsFiJHCEYB2YgBE5gBzNxEyjVHYcOxKKDfquRE6u39wFXh6dADJaccG4HLsANIIEb89PnaEvSYLG2kYAG0G+3YMnh4fDxbfe4wkAS47gAAyShsA2iSWUgsiYHfJMCF2ZKDVA9AkET4WbhgvB6OxxeoiuZZRVT/2BFjQfOemMX53qNn+e5fA42OtAOCYiYXNR4PznL4LJoLA1G8rQjjCTCmxc9+GzU4oNXvonr9avTUZPc7QdyHH0j4mgIqQVZQHq1VvAgRKf7MRKISZPWAG0ONXq1Vg6WYahMIbYz24pJ6ECYIyf7EiBBGm3/da0c6KX/ifTnv9P74iu66G3iUAI4+KoCNpeNS8rha9ifnkfmlcLO+n816+WL3mEVVcY2ew4xEtqsgBjUWEQkWsfFssWhdgPM0xoBg8iKl2JF8s3kpngCtMo3jsNljkUDAmYQFVWC9+tAgHeQ93AR/8WKw9d6MMWWFdBn0OJsJsjERZLn4QomOsWmmrpk9Kn0eYxpGiMfBG7dZ0FrcW8B2N1PoV9zkEUehn1b2hy68lxg/F0owVaXzW7Y0j6kwZuiqhUIaW8M54F9Olcq0irF0R1vAkfTdAFmwaKhjDUgfCur39n+NwF9ZrFhnMWm5YiM737L0/GHkxtYD4RKIWILz1+jf86/Vv69I4fSTRTNojAxgIdPUgCE7VjXhzhHAEJ1/nUUSl4qTHKeDyuMnCycCzjiCwyUYsWK9fofzhxIC8rtcBi2SlqPeEnu7/rekGwcutwhTHhKoYHlWvEa8u6FVN17D/Or3Ncfu/Wu5R7I2bmNECRiYYRpuaYtKiBa+0u0j9K7aguMFZZvTvVvUCFuoce5ygSmA9xlcRDR8iyzaZqVq50Coc1zBw8WezfBEfmqBGX+8QXLs1HY9tV3aMMeQSp4A6aP6qdx4aNHyMWnxBHbpwzTIW9vadkGTf/1BPdYhxsqrR7zuGoD4/6pp+iKVkaY3zWGxHHx55TuJxXZa1RSmwIyAyeoGVlf4wG9CBLD755Nx1ehHHub9e+3lBpxUh+0DuuO4ef/H5AXR0gkpg+EofjQed1ej8VsTuEk6T8cno/54cRyc2zms3Bcr+4Esvazz9C/IOYWlESNseoWtU3n5V3tYCDEA8tAce5j3enFyc/scT/Pno4qSLi9HHhf8f8eOIRf9lFswAAAAASUVORK5CYII=" + } + }, + { "type": "previous", "width": 44 }, + { "type": "play", "width": 44 }, + { "type": "next", "width": 44 }, { "type": "weather", "refreshInterval": 1800 }, - { "type": "sleep" }, - { "type": "battery" }, - { "type": "timeButton" }, + { "type": "sleep", "width": 44 }, + { "type": "volumeDown", "width": 34, "align": "right" }, + { "type": "volume", "width": 60, "align": "right" }, + { "type": "volumeUp", "width": 34, "align": "right" }, + { "type": "battery", "align": "right" }, + { "type": "timeButton", "align": "right" } ] diff --git a/build.sh b/build.sh index 6bf55d8..c4c76a1 100755 --- a/build.sh +++ b/build.sh @@ -17,3 +17,7 @@ rm -r App.xcarchive # Prerequisite: npm i -g create-dmg create-dmg "${NAME}.app" + +VERSION=`mdls -raw -name kMDItemVersion MTMR.app` +echo $VERSION +zip -r "${NAME}v${VERSION}.zip" "${NAME}.app"