Skip to content

Commit

Permalink
Render TSD camera in ATV. No countdown implemented yet to indicate wh…
Browse files Browse the repository at this point in the history
…en camera will refresh again

Issue #564
  • Loading branch information
gdombiak committed Feb 12, 2022
1 parent d4dcf2e commit f93aa6a
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 2 deletions.
42 changes: 42 additions & 0 deletions OctoPod TV/CameraService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ class CameraService: ObservableObject {
private var preemptiveAuthentication: Bool = false
private var isStreamPathFromSettings: Bool = true

/// Timer to fetch new image when using The Spaghetti Detective
private var tsdTimer: Timer?
private var tsdCountdown = 0

/// Render next camera
func renderNext() {
renderCamera(index: cameraIndex + 1)
Expand Down Expand Up @@ -64,6 +68,7 @@ class CameraService: ObservableObject {

func disconnectFromServer() {
streamingController?.stop()
tsdTimer?.invalidate()
player?.pause()
detailedPlayer?.pause()
playing = false
Expand Down Expand Up @@ -180,6 +185,24 @@ class CameraService: ObservableObject {
// Disable volume by default
detailedPlayer?.isMuted = true
}

fileprivate func renderTSDImage(image: UIImage?, error: String?) {
if let receivedImage = image {
DispatchQueue.main.async {
// Hide error messages since an image will be rendered (so that means that it worked!)
self.errorMessage = nil
// Render image
self.image = receivedImage
self.imageRatio = receivedImage.size.height / receivedImage.size.width
}
} else if let message = error {
DispatchQueue.main.async {
self.image = nil
// Display error messages
self.errorMessage = message
}
}
}

/// Stops rendering any previous URL and starts rendering the requested camera
/// Needs to be called from main thread
Expand All @@ -193,6 +216,7 @@ class CameraService: ObservableObject {

// Stop any video since it will be replaced with a new one
streamingController?.stop()
tsdTimer?.invalidate()
player?.pause()
detailedPlayer?.pause()

Expand All @@ -211,8 +235,26 @@ class CameraService: ObservableObject {
player!.play()
}

} else if CameraUtils.shared.isTLS(cameraURL: url) {
tsdTimer = Timer(fire: Date(), interval: 1, repeats: true, block: { (timer: Timer) in
if self.tsdCountdown == 0 {
// We need to make call Webcam snapshot API to then fetch Image from returned URL
CameraUtils.shared.renderImage(cameraURL: url, imageOrientation: imageOrientation, username: self.username, password: self.password, preemptive: true, timeoutInterval: 5.0) { (image: UIImage?, error: String?) in
self.renderTSDImage(image: image, error: error)
}
// Reset counter to 10 seconds since image changes every 10 seconds
self.tsdCountdown = 10
} else {
self.tsdCountdown -= 1
}
// DispatchQueue.main.async {
// self.countdownProgressView.showProgress(percent: Float(self.tsdCountdown * 10))
// }
})
RunLoop.main.add(tsdTimer!, forMode: .common)
} else {
// Clean up any previous HLS config
tsdTimer?.invalidate()
player = nil
detailedPlayer = nil
prepareForMJPEGRendering()
Expand Down
11 changes: 10 additions & 1 deletion OctoPod/CameraUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class CameraUtils {
if isHLS(url: cameraURL.absoluteString) {
// Render image from HLS camera
renderHLSImage(cameraURL: cameraURL, imageOrientation: imageOrientation, username: username, password: password, completion: completion)
} else if let host = cameraURL.host, host.hasSuffix("thespaghettidetective.com") {
} else if isTLS(cameraURL: cameraURL) {
// The Spaghetti Detective has its own special logic
renderTLSImage(cameraURL: cameraURL, imageOrientation: imageOrientation, username: username, password: password, preemptive: preemptive, timeoutInterval: timeoutInterval, completion: completion)
} else {
Expand All @@ -26,10 +26,19 @@ class CameraUtils {
}
}

/// Returns true if camera URL is rendering HLS videos
func isHLS(url: String) -> Bool {
return url.hasSuffix(".m3u8")
}

/// Returns true if camera URL is hosted via The Spaghetti Detective
func isTLS(cameraURL: URL) -> Bool {
if let host = cameraURL.host, host.hasSuffix("thespaghettidetective.com") {
return true
}
return false
}

func absoluteURL(hostname: String, streamUrl: String) -> String {
if streamUrl.isEmpty {
// Should never happen but let's be cautious
Expand Down
6 changes: 5 additions & 1 deletion OctoPod/UIUtils.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import Foundation
import UIKit
import AVKit
import SafariServices
#if !os(tvOS)
import SafariServices
#endif

class UIUtils {

Expand Down Expand Up @@ -29,10 +31,12 @@ class UIUtils {
// Execute done block on dismiss
done?()
}))
#if !os(tvOS)
alert.addAction(UIAlertAction(title: NSLocalizedString("Learn More", comment: ""), style: .default, handler: { (UIAlertAction) -> Void in
let vc = SFSafariViewController(url: moreURL)
presenter.present(vc, animated: false, completion: done)
}))
#endif
presenter.present(alert, animated: true) { () -> Void in
// Nothing to do here
}
Expand Down

0 comments on commit f93aa6a

Please sign in to comment.