diff --git a/Aerial.xcodeproj/project.pbxproj b/Aerial.xcodeproj/project.pbxproj
index ebcbb5da..af4e176c 100644
--- a/Aerial.xcodeproj/project.pbxproj
+++ b/Aerial.xcodeproj/project.pbxproj
@@ -698,7 +698,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "if which swiftlint >/dev/null; then\n if [ -z \"$CI\" ]; then\n make --directory=${SRCROOT} xcode-lint\n fi\nelse\n echo \"warning: SwiftLint not installed, install using `brew install swiftlint`\"\nfi\n";
+ shellScript = "#if which swiftlint >/dev/null; then\n# if [ -z \"$CI\" ]; then\n# make --directory=${SRCROOT} xcode-lint\n# fi\n#else\n# echo \"warning: SwiftLint not installed, install using `brew install swiftlint`\"\n#fi\nif which swiftlint >/dev/null; then\n swiftlint autocorrect\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
};
910394578D35CCEBAEE0D456 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
@@ -748,7 +748,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "if which swiftlint >/dev/null; then\n if [ -z \"$CI\" ]; then\n make --directory=${SRCROOT} xcode-lint\n fi\nelse\n echo \"warning: SwiftLint not installed, install using `brew install swiftlint`\"\nfi";
+ shellScript = "#if which swiftlint >/dev/null; then\n# if [ -z \"$CI\" ]; then\n# make --directory=${SRCROOT} xcode-lint\n# fi\n#else\n# echo \"warning: SwiftLint not installed, install using `brew install swiftlint`\"\n#fi\nif which swiftlint >/dev/null; then\n swiftlint autocorrect\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
};
/* End PBXShellScriptBuildPhase section */
diff --git a/Aerial/Source/Controllers/Preferences.swift b/Aerial/Source/Controllers/Preferences.swift
index d93c2cfc..01841ec5 100644
--- a/Aerial/Source/Controllers/Preferences.swift
+++ b/Aerial/Source/Controllers/Preferences.swift
@@ -77,6 +77,8 @@ final class Preferences {
case newDisplayMode = "newDisplayMode"
case newViewingMode = "newViewingMode"
case newDisplayDict = "newDisplayDict"
+ case logMilliseconds = "logMilliseconds"
+ case horizontalMargin = "horizontalMargin"
}
enum NewDisplayMode: Int {
@@ -84,7 +86,7 @@ final class Preferences {
}
enum NewViewingMode: Int {
- case independant, mirrored, spanned
+ case independent, mirrored, spanned
}
enum BetaCheckFrequency: Int {
@@ -211,8 +213,10 @@ final class Preferences {
defaultValues[.allowBetas] = false
defaultValues[.betaCheckFrequency] = BetaCheckFrequency.daily
defaultValues[.newDisplayMode] = NewDisplayMode.allDisplays
- defaultValues[.newViewingMode] = NewViewingMode.independant
+ defaultValues[.newViewingMode] = NewViewingMode.independent
defaultValues[.newDisplayDict] = [String: Bool]()
+ defaultValues[.logMilliseconds] = false
+ defaultValues[.horizontalMargin] = 0
// Set today's date as default
let dateFormatter = DateFormatter()
@@ -249,6 +253,15 @@ final class Preferences {
}
}
+ var horizontalMargin: Double? {
+ get {
+ return optionalValue(forIdentifier: .horizontalMargin)
+ }
+ set {
+ setValue(forIdentifier: .horizontalMargin, value: newValue)
+ }
+ }
+
var newDisplayMode: Int? {
get {
return optionalValue(forIdentifier: .newDisplayMode)
@@ -303,6 +316,15 @@ final class Preferences {
}
}
+ var logMilliseconds: Bool {
+ get {
+ return value(forIdentifier: .logMilliseconds)
+ }
+ set {
+ setValue(forIdentifier: .logMilliseconds, value: newValue)
+ }
+ }
+
var allowBetas: Bool {
get {
return value(forIdentifier: .allowBetas)
diff --git a/Aerial/Source/Controllers/PreferencesWindowController.swift b/Aerial/Source/Controllers/PreferencesWindowController.swift
index 63f160d0..e7229585 100644
--- a/Aerial/Source/Controllers/PreferencesWindowController.swift
+++ b/Aerial/Source/Controllers/PreferencesWindowController.swift
@@ -210,7 +210,11 @@ final class PreferencesWindowController: NSWindowController, NSOutlineViewDataSo
@IBOutlet var newDisplayModePopup: NSPopUpButton!
@IBOutlet var newViewingModePopup: NSPopUpButton!
@IBOutlet var displayInstructionLabel: NSTextField!
+ @IBOutlet var quitConfirmationPanel: NSPanel!
+ @IBOutlet var logMillisecondsButton: NSButton!
+ @IBOutlet var displayMarginBox: NSBox!
+ @IBOutlet var horizontalDisplayMarginTextfield: NSTextField!
var player: AVPlayer = AVPlayer()
var videos: [AerialVideo]?
@@ -419,14 +423,18 @@ final class PreferencesWindowController: NSWindowController, NSOutlineViewDataSo
if !preferences.allowSkips {
rightArrowKeyPlaysNextCheckbox.state = .off
}
+ horizontalDisplayMarginTextfield.doubleValue = preferences.horizontalMargin!
- // Aerial panel
+ // Advanced panel
if preferences.debugMode {
debugModeCheckbox.state = .on
}
if preferences.logToDisk {
logToDiskCheckbox.state = .on
}
+ if preferences.logMilliseconds {
+ logMillisecondsButton.state = .on
+ }
// Text panel
if preferences.showClock {
@@ -660,7 +668,23 @@ final class PreferencesWindowController: NSWindowController, NSOutlineViewDataSo
}
@IBAction func close(_ sender: AnyObject?) {
- // This seems needed for screensavers as our lifecycle is different from a regular app
+ // We ask for confirmation in case downloads are ongoing
+ if !downloadProgressIndicator.isHidden {
+ quitConfirmationPanel.makeKeyAndOrderFront(self)
+ } else {
+ // This seems needed for screensavers as our lifecycle is different from a regular app
+ preferences.synchronize()
+ logPanel.close()
+ if appMode {
+ NSApplication.shared.terminate(nil)
+ } else {
+ window?.sheetParent?.endSheet(window!)
+ }
+ }
+ }
+
+ @IBAction func confirmQuitClick(_ sender: Any) {
+ quitConfirmationPanel.close()
preferences.synchronize()
logPanel.close()
if appMode {
@@ -670,6 +694,10 @@ final class PreferencesWindowController: NSWindowController, NSOutlineViewDataSo
}
}
+ @IBAction func cancelQuitClick(_ sender: Any) {
+ quitConfirmationPanel.close()
+ }
+
// MARK: Video playback
// Rewind preview video when reaching end
@@ -861,6 +889,17 @@ final class PreferencesWindowController: NSWindowController, NSOutlineViewDataSo
debugLog("UI newViewingModeClick: \(sender.indexOfSelectedItem)")
preferences.newViewingMode = sender.indexOfSelectedItem
displayView.needsDisplay = true
+
+ if preferences.newViewingMode == Preferences.NewViewingMode.spanned.rawValue {
+ displayMarginBox.isHidden = false
+ } else {
+ displayMarginBox.isHidden = true
+ }
+ }
+
+ @IBAction func horizontalDisplayMarginChange(_ sender: NSTextField) {
+ debugLog("UI horizontalDisplayMarginChange \(sender.stringValue)")
+ preferences.horizontalMargin = sender.doubleValue
}
// MARK: - Text panel
@@ -1459,6 +1498,13 @@ final class PreferencesWindowController: NSWindowController, NSOutlineViewDataSo
}
// MARK: - Advanced panel
+
+ @IBAction func logMillisecondsClick(_ button: NSButton) {
+ let onState = button.state == .on
+ preferences.logMilliseconds = onState
+ debugLog("UI logMilliseconds: \(onState)")
+ }
+
@IBAction func logButtonClick(_ sender: NSButton) {
logTableView.reloadData()
if logPanel.isVisible {
diff --git a/Aerial/Source/Models/DisplayDetection.swift b/Aerial/Source/Models/DisplayDetection.swift
index 8cb06ac7..1cc8795a 100644
--- a/Aerial/Source/Models/DisplayDetection.swift
+++ b/Aerial/Source/Models/DisplayDetection.swift
@@ -42,6 +42,9 @@ final class DisplayDetection: NSObject {
static let sharedInstance = DisplayDetection()
var screens = [Screen]()
+ var cmInPoints: CGFloat = 40
+ var maxLeftScreens: CGFloat = 0
+ var maxBelowScreens: CGFloat = 0
// MARK: - Lifecycle
override init() {
@@ -72,8 +75,13 @@ final class DisplayDetection: NSObject {
var rect = CGDisplayBounds(currentDisplay)
if isMain == 0 {
rect = convertTopLeftToBottomLeft(rect: rect)
+ } else {
+ // We calculate the equivalent of a centimeter in points on the main screen as a reference
+ let mmsize = CGDisplayScreenSize(currentDisplay)
+ let wide = CGDisplayPixelsWide(currentDisplay)
+ cmInPoints = CGFloat(wide) / CGFloat(mmsize.width) * 10
+ debugLog("1cm = \(cmInPoints) points")
}
-
screens.append(Screen(id: currentDisplay,
width: CGDisplayPixelsWide(currentDisplay),
height: CGDisplayPixelsHigh(currentDisplay),
@@ -97,6 +105,7 @@ final class DisplayDetection: NSObject {
for screen in screens {
debugLog("\(screen)")
}
+
debugLog("\(getGlobalScreenRect())")
debugLog("***Display Detection Done***")
}
@@ -106,12 +115,33 @@ final class DisplayDetection: NSObject {
func calculateZeroedOrigins() {
let orect = getGlobalScreenRect()
+ // First we check for the screen relative position and calculate how many screens we have horizontally
+ // TODO Vertical + H/V mix
for screen in screens {
- screen.zeroedOrigin = CGPoint(x: screen.bottomLeftFrame.origin.x - orect.origin.x,
+ debugLog("src orig : \(screen.bottomLeftFrame.origin)")
+ var leftScreens: CGFloat = 0
+ // Very rough, horizontal spans only
+ for otherScreen in screens {
+ if otherScreen.bottomLeftFrame.origin.x != screen.bottomLeftFrame.origin.x &&
+ otherScreen.bottomLeftFrame.origin.x < screen.bottomLeftFrame.origin.x {
+ leftScreens += 1
+ }
+ }
+
+ if leftScreens > maxLeftScreens {
+ maxLeftScreens = leftScreens
+ }
+
+ screen.zeroedOrigin = CGPoint(x: screen.bottomLeftFrame.origin.x - orect.origin.x + (leftScreens * leftMargin()),
y: screen.bottomLeftFrame.origin.y - orect.origin.y)
}
}
+ func leftMargin() -> CGFloat {
+ let preferences = Preferences.sharedInstance
+ return cmInPoints * CGFloat(preferences.horizontalMargin!)
+ }
+
func findScreenWith(frame: CGRect) -> Screen? {
for screen in screens where frame == screen.bottomLeftFrame {
return screen
@@ -146,7 +176,7 @@ final class DisplayDetection: NSObject {
}
}
- return CGRect(x: minX, y: minY, width: maxX-minX, height: maxY-minY)
+ return CGRect(x: minX, y: minY, width: maxX-minX+(maxLeftScreens*leftMargin()), height: maxY-minY)
}
func getZeroedActiveSpannedRect() -> CGRect {
@@ -172,7 +202,7 @@ final class DisplayDetection: NSObject {
let orect = getGlobalScreenRect()
minX -= orect.origin.x
minY -= orect.origin.y
- return CGRect(x: minX, y: minY, width: width, height: height)
+ return CGRect(x: minX, y: minY, width: width+(maxLeftScreens*leftMargin()), height: height)
}
// NSScreen coordinates are with a bottom left origin, whereas CGDisplay
diff --git a/Aerial/Source/Models/ErrorLog.swift b/Aerial/Source/Models/ErrorLog.swift
index 1730bb31..b34d288a 100644
--- a/Aerial/Source/Models/ErrorLog.swift
+++ b/Aerial/Source/Models/ErrorLog.swift
@@ -77,7 +77,11 @@ func Log(level: ErrorLevel, message: String) {
if preferences.logToDisk {
DispatchQueue.main.async {
let dateFormatter = DateFormatter()
- dateFormatter.dateFormat = "yyyy-MM-dd' 'HH:mm:ss"
+ if preferences.logMilliseconds {
+ dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
+ } else {
+ dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
+ }
let string = dateFormatter.string(from: Date()) + " : " + message + "\n"
// tmpOverride
diff --git a/Aerial/Source/Views/AerialView.swift b/Aerial/Source/Views/AerialView.swift
index 3d682a97..a931a610 100644
--- a/Aerial/Source/Views/AerialView.swift
+++ b/Aerial/Source/Views/AerialView.swift
@@ -269,9 +269,9 @@ final class AerialView: ScreenSaverView {
}
} else {
// If we don't know this screen, we disable
- debugLog("This is an unknown display, disabling")
- isDisabled = true
- return
+ //debugLog("This is an unknown display, disabling")
+ //isDisabled = false
+ //return
}
} else {
AerialView.previewView = self
@@ -356,6 +356,7 @@ final class AerialView: ScreenSaverView {
debugLog("\(self.description) setting up player layer with bounds/frame: \(layer.bounds) / \(layer.frame)")
playerLayer = AVPlayerLayer(player: player)
+
if #available(OSX 10.10, *) {
playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
}
@@ -370,7 +371,9 @@ final class AerialView: ScreenSaverView {
y: zRect.origin.y - scr.zeroedOrigin.y,
width: zRect.width,
height: zRect.height)
+ debugLog("tRect : \(tRect)")
playerLayer.frame = tRect
+ //playerLayer.bounds = layer.bounds
} else {
errorLog("This is an unknown screen in span mode, this is not good")
playerLayer.frame = layer.bounds
@@ -378,7 +381,6 @@ final class AerialView: ScreenSaverView {
} else {
playerLayer.frame = layer.bounds
}
-
layer.addSublayer(playerLayer)
textLayer = CATextLayer()
@@ -630,10 +632,14 @@ final class AerialView: ScreenSaverView {
if preferences.allowSkips {
if event.keyCode == 124 {
- //playNextVideo()
- // We need to skip forward all our views
- for view in AerialView.instanciatedViews {
- view.playNextVideo()
+ // If we share, just call this on our main view
+ if AerialView.sharingPlayers {
+ playNextVideo()
+ } else {
+ // If we do independant playback we have to skip all views
+ for view in AerialView.instanciatedViews {
+ view.playNextVideo()
+ }
}
} else {
self.nextResponder!.keyDown(with: event)
diff --git a/Aerial/Source/Views/DisplayView.swift b/Aerial/Source/Views/DisplayView.swift
index bbe7a48a..316d7b94 100644
--- a/Aerial/Source/Views/DisplayView.swift
+++ b/Aerial/Source/Views/DisplayView.swift
@@ -115,7 +115,7 @@ class DisplayView: NSView {
let sInRect = sRect.insetBy(dx: 1, dy: 1)
- if preferences.newViewingMode == Preferences.NewViewingMode.independant.rawValue ||
+ if preferences.newViewingMode == Preferences.NewViewingMode.independent.rawValue ||
preferences.newViewingMode == Preferences.NewViewingMode.mirrored.rawValue {
if displayDetection.isScreenActive(id: screen.id) {
let bundle = Bundle(for: PreferencesWindowController.self)
@@ -128,7 +128,7 @@ class DisplayView: NSView {
}
// Show difference images in independant mode to simulate
- if preferences.newViewingMode == Preferences.NewViewingMode.independant.rawValue {
+ if preferences.newViewingMode == Preferences.NewViewingMode.independent.rawValue {
if idx < 2 {
idx += 1
} else {
diff --git a/Resources/Info.plist b/Resources/Info.plist
index 3c5dbb35..66eef456 100644
--- a/Resources/Info.plist
+++ b/Resources/Info.plist
@@ -15,11 +15,11 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- 1.4.98beta1
+ 1.4.99beta2
CFBundleSignature
????
CFBundleVersion
- 1.4.98beta1
+ 1.4.99beta2
LSApplicationCategoryType
LSMinimumSystemVersion
diff --git a/Resources/PreferencesWindow.xib b/Resources/PreferencesWindow.xib
index 72c339ff..19cbfe11 100644
--- a/Resources/PreferencesWindow.xib
+++ b/Resources/PreferencesWindow.xib
@@ -45,6 +45,7 @@
+
@@ -69,6 +70,7 @@
+
@@ -79,6 +81,7 @@
+
@@ -112,6 +115,7 @@
+
@@ -633,6 +637,84 @@ is disabled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1777,7 +1859,7 @@ Shift, but macOS 10.12.4 or above and a compatible Mac are required)
-
+
@@ -1786,7 +1868,7 @@ Shift, but macOS 10.12.4 or above and a compatible Mac are required)
-
+
@@ -1799,7 +1881,7 @@ Shift, but macOS 10.12.4 or above and a compatible Mac are required)
-
+
@@ -1808,7 +1890,7 @@ Shift, but macOS 10.12.4 or above and a compatible Mac are required)
-
+
@@ -1898,7 +1980,7 @@ Shift, but macOS 10.12.4 or above and a compatible Mac are required)
+
@@ -2580,6 +2673,59 @@ Unless you want to manually manage your updates, we highly recommand you leave t
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ You are currently downloading videos, if you quit the configuration panel those downloads will be cancelled. Are you sure you want to quit ?
+
+
+
+
+
+
+
+
+
+