summaryrefslogtreecommitdiff
path: root/CCCB Display
diff options
context:
space:
mode:
Diffstat (limited to 'CCCB Display')
-rw-r--r--CCCB Display/AppDelegate.swift1
-rw-r--r--CCCB Display/Assets.xcassets/AppIcon.appiconset/Contents.json1
-rw-r--r--CCCB Display/Assets.xcassets/AppIcon.appiconset/IMG_4898.jpegbin0 -> 534617 bytes
-rw-r--r--CCCB Display/Assets.xcassets/IMG_4898.imageset/Contents.json21
-rw-r--r--CCCB Display/Assets.xcassets/IMG_4898.imageset/IMG_4898.jpegbin0 -> 534617 bytes
-rw-r--r--CCCB Display/Base.lproj/LaunchScreen.storyboard29
-rw-r--r--CCCB Display/Base.lproj/Main.storyboard129
-rw-r--r--CCCB Display/ConfigController.swift35
-rw-r--r--CCCB Display/ViewController.swift336
9 files changed, 539 insertions, 13 deletions
diff --git a/CCCB Display/AppDelegate.swift b/CCCB Display/AppDelegate.swift
index 8639c64..a3e61dc 100644
--- a/CCCB Display/AppDelegate.swift
+++ b/CCCB Display/AppDelegate.swift
@@ -14,6 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
14 14
15 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 15 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
16 // Override point for customization after application launch. 16 // Override point for customization after application launch.
17 UIApplication.shared.isIdleTimerDisabled = true
17 return true 18 return true
18 } 19 }
19 20
diff --git a/CCCB Display/Assets.xcassets/AppIcon.appiconset/Contents.json b/CCCB Display/Assets.xcassets/AppIcon.appiconset/Contents.json
index 13613e3..bfe77c1 100644
--- a/CCCB Display/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/CCCB Display/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -1,6 +1,7 @@
1{ 1{
2 "images" : [ 2 "images" : [
3 { 3 {
4 "filename" : "IMG_4898.jpeg",
4 "idiom" : "universal", 5 "idiom" : "universal",
5 "platform" : "ios", 6 "platform" : "ios",
6 "size" : "1024x1024" 7 "size" : "1024x1024"
diff --git a/CCCB Display/Assets.xcassets/AppIcon.appiconset/IMG_4898.jpeg b/CCCB Display/Assets.xcassets/AppIcon.appiconset/IMG_4898.jpeg
new file mode 100644
index 0000000..b9f2603
--- /dev/null
+++ b/CCCB Display/Assets.xcassets/AppIcon.appiconset/IMG_4898.jpeg
Binary files differ
diff --git a/CCCB Display/Assets.xcassets/IMG_4898.imageset/Contents.json b/CCCB Display/Assets.xcassets/IMG_4898.imageset/Contents.json
new file mode 100644
index 0000000..ce6efb2
--- /dev/null
+++ b/CCCB Display/Assets.xcassets/IMG_4898.imageset/Contents.json
@@ -0,0 +1,21 @@
1{
2 "images" : [
3 {
4 "filename" : "IMG_4898.jpeg",
5 "idiom" : "universal",
6 "scale" : "1x"
7 },
8 {
9 "idiom" : "universal",
10 "scale" : "2x"
11 },
12 {
13 "idiom" : "universal",
14 "scale" : "3x"
15 }
16 ],
17 "info" : {
18 "author" : "xcode",
19 "version" : 1
20 }
21}
diff --git a/CCCB Display/Assets.xcassets/IMG_4898.imageset/IMG_4898.jpeg b/CCCB Display/Assets.xcassets/IMG_4898.imageset/IMG_4898.jpeg
new file mode 100644
index 0000000..b9f2603
--- /dev/null
+++ b/CCCB Display/Assets.xcassets/IMG_4898.imageset/IMG_4898.jpeg
Binary files differ
diff --git a/CCCB Display/Base.lproj/LaunchScreen.storyboard b/CCCB Display/Base.lproj/LaunchScreen.storyboard
index 865e932..37c47c1 100644
--- a/CCCB Display/Base.lproj/LaunchScreen.storyboard
+++ b/CCCB Display/Base.lproj/LaunchScreen.storyboard
@@ -1,8 +1,10 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?> 1<?xml version="1.0" encoding="UTF-8"?>
2<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> 2<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
3 <device id="retina6_12" orientation="landscape" appearance="light"/>
3 <dependencies> 4 <dependencies>
4 <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/> 5 <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
5 <capability name="Safe area layout guides" minToolsVersion="9.0"/> 6 <capability name="Safe area layout guides" minToolsVersion="9.0"/>
7 <capability name="System colors in document resources" minToolsVersion="11.0"/>
6 <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> 8 <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
7 </dependencies> 9 </dependencies>
8 <scenes> 10 <scenes>
@@ -11,10 +13,21 @@
11 <objects> 13 <objects>
12 <viewController id="01J-lp-oVM" sceneMemberID="viewController"> 14 <viewController id="01J-lp-oVM" sceneMemberID="viewController">
13 <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> 15 <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
14 <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> 16 <rect key="frame" x="0.0" y="0.0" width="852" height="393"/>
15 <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> 17 <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
16 <color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> 18 <subviews>
19 <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="IMG_4898" translatesAutoresizingMaskIntoConstraints="NO" id="pnd-eL-XdQ">
20 <rect key="frame" x="59" y="0.0" width="734" height="372"/>
21 </imageView>
22 </subviews>
17 <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/> 23 <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
24 <color key="backgroundColor" systemColor="systemBackgroundColor"/>
25 <constraints>
26 <constraint firstItem="pnd-eL-XdQ" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" id="Nv3-O9-veR"/>
27 <constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="pnd-eL-XdQ" secondAttribute="bottom" id="fB9-uM-dp6"/>
28 <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="pnd-eL-XdQ" secondAttribute="trailing" id="i5C-Km-vv3"/>
29 <constraint firstItem="pnd-eL-XdQ" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" id="wKN-64-4YA"/>
30 </constraints>
18 </view> 31 </view>
19 </viewController> 32 </viewController>
20 <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> 33 <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -22,4 +35,10 @@
22 <point key="canvasLocation" x="53" y="375"/> 35 <point key="canvasLocation" x="53" y="375"/>
23 </scene> 36 </scene>
24 </scenes> 37 </scenes>
38 <resources>
39 <image name="IMG_4898" width="1024" height="1024"/>
40 <systemColor name="systemBackgroundColor">
41 <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
42 </systemColor>
43 </resources>
25</document> 44</document>
diff --git a/CCCB Display/Base.lproj/Main.storyboard b/CCCB Display/Base.lproj/Main.storyboard
index 25a7638..247b634 100644
--- a/CCCB Display/Base.lproj/Main.storyboard
+++ b/CCCB Display/Base.lproj/Main.storyboard
@@ -1,24 +1,143 @@
1<?xml version="1.0" encoding="UTF-8"?> 1<?xml version="1.0" encoding="UTF-8"?>
2<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> 2<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
3 <device id="retina6_12" orientation="landscape" appearance="light"/>
3 <dependencies> 4 <dependencies>
4 <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/> 5 <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
5 <capability name="Safe area layout guides" minToolsVersion="9.0"/> 6 <capability name="Safe area layout guides" minToolsVersion="9.0"/>
7 <capability name="System colors in document resources" minToolsVersion="11.0"/>
6 <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> 8 <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
7 </dependencies> 9 </dependencies>
8 <scenes> 10 <scenes>
9 <!--View Controller--> 11 <!--View Controller-->
10 <scene sceneID="tne-QT-ifu"> 12 <scene sceneID="tne-QT-ifu">
11 <objects> 13 <objects>
12 <viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController"> 14 <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="CCCB_Display" customModuleProvider="target" sceneMemberID="viewController">
13 <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> 15 <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
14 <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> 16 <rect key="frame" x="0.0" y="0.0" width="852" height="393"/>
15 <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> 17 <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
16 <color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> 18 <subviews>
19 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Zg1-dS-4VN">
20 <rect key="frame" x="0.0" y="0.0" width="852" height="393"/>
21 <color key="backgroundColor" systemColor="systemBackgroundColor"/>
22 </view>
23 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LB5-99-rhM">
24 <rect key="frame" x="689" y="8" width="72" height="35"/>
25 <state key="normal" title="Button"/>
26 <buttonConfiguration key="configuration" style="filled" title="config"/>
27 <connections>
28 <segue destination="Srg-Ai-hZD" kind="popoverPresentation" popoverAnchorView="LB5-99-rhM" id="qNt-fx-jP2">
29 <popoverArrowDirection key="popoverArrowDirection" up="YES" down="YES" left="YES" right="YES"/>
30 </segue>
31 </connections>
32 </button>
33 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="right" contentVerticalAlignment="bottom" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4IW-d6-qWW">
34 <rect key="frame" x="630" y="8" width="51" height="35"/>
35 <state key="normal" title="Button"/>
36 <buttonConfiguration key="configuration" style="filled" title="Flip"/>
37 <connections>
38 <action selector="switchCameraSideWithSender:" destination="BYZ-38-t0r" eventType="touchUpInside" id="15B-T0-yhg"/>
39 </connections>
40 </button>
41 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FPx-ZU-vSE">
42 <rect key="frame" x="59" y="8" width="80" height="22"/>
43 <color key="backgroundColor" systemColor="systemGreenColor"/>
44 <fontDescription key="fontDescription" type="system" pointSize="17"/>
45 <nil key="textColor"/>
46 <nil key="highlightedColor"/>
47 </label>
48 </subviews>
17 <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/> 49 <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
50 <color key="backgroundColor" systemColor="systemBackgroundColor"/>
51 <constraints>
52 <constraint firstItem="LB5-99-rhM" firstAttribute="leading" secondItem="4IW-d6-qWW" secondAttribute="trailing" constant="8" id="0JW-YO-OfQ"/>
53 <constraint firstItem="FPx-ZU-vSE" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="8" id="2HN-cV-t4S"/>
54 <constraint firstItem="FPx-ZU-vSE" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" id="3qY-jD-MCQ"/>
55 <constraint firstItem="Zg1-dS-4VN" firstAttribute="bottom" secondItem="8bC-Xf-vdC" secondAttribute="bottom" id="8Uw-BH-OnX"/>
56 <constraint firstItem="Zg1-dS-4VN" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="AJu-22-uph"/>
57 <constraint firstItem="Zg1-dS-4VN" firstAttribute="top" secondItem="8bC-Xf-vdC" secondAttribute="top" id="EDS-vg-saF"/>
58 <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="LB5-99-rhM" secondAttribute="trailing" constant="32" id="FMt-88-9e3"/>
59 <constraint firstItem="4IW-d6-qWW" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="8" id="G8m-hM-E2u"/>
60 <constraint firstItem="LB5-99-rhM" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="8" id="OP9-7G-8by"/>
61 <constraint firstAttribute="trailing" secondItem="Zg1-dS-4VN" secondAttribute="trailing" id="esB-po-Jgq"/>
62 <constraint firstItem="Zg1-dS-4VN" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="wPB-mw-ptE"/>
63 </constraints>
18 </view> 64 </view>
65 <connections>
66 <outlet property="cameraView" destination="Zg1-dS-4VN" id="27A-lq-3JJ"/>
67 <outlet property="frameRateLabel" destination="FPx-ZU-vSE" id="twM-qM-WQM"/>
68 </connections>
19 </viewController> 69 </viewController>
20 <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> 70 <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
21 </objects> 71 </objects>
72 <point key="canvasLocation" x="111.9718309859155" y="-2.2900763358778624"/>
73 </scene>
74 <!--Config Controller-->
75 <scene sceneID="Ozy-FI-kCz">
76 <objects>
77 <viewController modalPresentationStyle="pageSheet" id="Srg-Ai-hZD" customClass="ConfigController" customModule="CCCB_Display" customModuleProvider="target" sceneMemberID="viewController">
78 <view key="view" contentMode="scaleToFill" id="RKC-6a-725">
79 <rect key="frame" x="0.0" y="0.0" width="852" height="393"/>
80 <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
81 <subviews>
82 <textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="IP Address" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="XB9-tI-41p">
83 <rect key="frame" x="210.99999999999997" y="68" width="401.33333333333326" height="35"/>
84 <fontDescription key="fontDescription" type="system" pointSize="14"/>
85 <textInputTraits key="textInputTraits"/>
86 </textField>
87 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Display Address" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eRN-cy-tvC">
88 <rect key="frame" x="80" y="75" width="123" height="21"/>
89 <fontDescription key="fontDescription" type="system" pointSize="17"/>
90 <nil key="textColor"/>
91 <nil key="highlightedColor"/>
92 </label>
93 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eoj-db-q0p">
94 <rect key="frame" x="705" y="68" width="65" height="35"/>
95 <state key="normal" title="Button"/>
96 <buttonConfiguration key="configuration" style="filled" title="Done"/>
97 <connections>
98 <action selector="donePressed:" destination="Srg-Ai-hZD" eventType="touchUpInside" id="RFf-QJ-Omk"/>
99 </connections>
100 </button>
101 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dKt-Le-k5D">
102 <rect key="frame" x="620.33333333333337" y="68" width="76.666666666666629" height="35"/>
103 <state key="normal" title="Button"/>
104 <buttonConfiguration key="configuration" style="filled" title="Cancel"/>
105 <connections>
106 <action selector="cancelPressed:" destination="Srg-Ai-hZD" eventType="touchUpInside" id="8qq-Jm-VhP"/>
107 </connections>
108 </button>
109 </subviews>
110 <viewLayoutGuide key="safeArea" id="D96-4o-bMR"/>
111 <color key="backgroundColor" systemColor="systemBackgroundColor"/>
112 <constraints>
113 <constraint firstItem="XB9-tI-41p" firstAttribute="top" secondItem="eoj-db-q0p" secondAttribute="top" id="1Aw-0G-Omh"/>
114 <constraint firstItem="XB9-tI-41p" firstAttribute="leading" secondItem="eRN-cy-tvC" secondAttribute="trailing" constant="8" id="3FR-zi-YS0"/>
115 <constraint firstItem="dKt-Le-k5D" firstAttribute="top" secondItem="eoj-db-q0p" secondAttribute="top" id="6db-VB-pbU"/>
116 <constraint firstItem="XB9-tI-41p" firstAttribute="centerY" secondItem="eRN-cy-tvC" secondAttribute="centerY" id="Ob5-Ea-9SL"/>
117 <constraint firstItem="XB9-tI-41p" firstAttribute="centerY" secondItem="eoj-db-q0p" secondAttribute="centerY" id="R2J-lD-arp"/>
118 <constraint firstItem="dKt-Le-k5D" firstAttribute="leading" secondItem="XB9-tI-41p" secondAttribute="trailing" constant="8" id="TNp-0v-8LR"/>
119 <constraint firstItem="eRN-cy-tvC" firstAttribute="leading" secondItem="D96-4o-bMR" secondAttribute="leading" constant="80" id="aD8-8R-LiO"/>
120 <constraint firstItem="eoj-db-q0p" firstAttribute="leading" secondItem="dKt-Le-k5D" secondAttribute="trailing" constant="8" id="dSO-oI-Wci"/>
121 <constraint firstItem="D96-4o-bMR" firstAttribute="trailing" secondItem="eoj-db-q0p" secondAttribute="trailing" constant="82" id="riC-ZY-AgB"/>
122 <constraint firstItem="XB9-tI-41p" firstAttribute="top" secondItem="D96-4o-bMR" secondAttribute="top" constant="68" id="sUl-XQ-UGi"/>
123 </constraints>
124 </view>
125 <extendedEdge key="edgesForExtendedLayout" bottom="YES"/>
126 <connections>
127 <outlet property="display_address" destination="XB9-tI-41p" id="EZU-kl-5r7"/>
128 </connections>
129 </viewController>
130 <placeholder placeholderIdentifier="IBFirstResponder" id="XVb-PU-k6x" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
131 </objects>
132 <point key="canvasLocation" x="904" y="-2"/>
22 </scene> 133 </scene>
23 </scenes> 134 </scenes>
135 <resources>
136 <systemColor name="systemBackgroundColor">
137 <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
138 </systemColor>
139 <systemColor name="systemGreenColor">
140 <color red="0.20392156862745098" green="0.7803921568627451" blue="0.34901960784313724" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
141 </systemColor>
142 </resources>
24</document> 143</document>
diff --git a/CCCB Display/ConfigController.swift b/CCCB Display/ConfigController.swift
new file mode 100644
index 0000000..92b6e37
--- /dev/null
+++ b/CCCB Display/ConfigController.swift
@@ -0,0 +1,35 @@
1//
2// ConfigController.swift
3// CCCB Display
4//
5// Created by Dirk Engling on 26.05.23.
6//
7
8import Foundation
9import UIKit
10
11
12class ConfigController: UIViewController {
13
14 @IBOutlet weak var display_address: UITextField!
15
16 override func viewWillAppear(_ animated: Bool) {
17 super.viewWillAppear(animated)
18 let defaults = UserDefaults.standard
19 if let ip = defaults.string(forKey: "Display_Address") {
20 display_address.text = ip
21 } else {
22 display_address.text = "172.23.42.29"
23 }
24 }
25
26 @IBAction func cancelPressed(_ sender: Any) {
27 self.dismiss(animated: true)
28 }
29
30 @IBAction func donePressed(_ sender: Any) {
31 self.dismiss(animated: true)
32 let defaults = UserDefaults.standard
33 defaults.set(display_address.text, forKey: "Display_Address")
34 }
35}
diff --git a/CCCB Display/ViewController.swift b/CCCB Display/ViewController.swift
index 53f3cee..d0f8dbe 100644
--- a/CCCB Display/ViewController.swift
+++ b/CCCB Display/ViewController.swift
@@ -6,14 +6,344 @@
6// 6//
7 7
8import UIKit 8import UIKit
9import AVFoundation
10import CoreImage
11import Network
9 12
10class ViewController: UIViewController { 13class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate, ObservableObject, AVCaptureVideoDataOutputSampleBufferDelegate {
14
15 @IBOutlet weak var frameRateLabel: UILabel!
16 @IBOutlet weak var cameraView: UIView!
17
18 var device: AVCaptureDevice?
19 var input: AVCaptureDeviceInput?
20 var prevLayer: AVCaptureVideoPreviewLayer?
21
22 private let captureSession = AVCaptureSession()
23 private let videoDataOutput = AVCaptureVideoDataOutput()
24 private let sessionQueue = DispatchQueue(label: "sessionQueue")
25 private let context = CIContext()
26
27// var hostUDP: NWEndpoint.Host = "172.23.42.29"
28 var hostUDP: NWEndpoint.Host?
29 var portUDP: NWEndpoint.Port = 2342
30 var connectionUDP: NWConnection?
31
32 var lastTimeStamp: CFTimeInterval = CACurrentMediaTime()
33
34 /* Physical Display control packet parameters: */
35 private let HEADERLEN = 10
36 private let WIDTH = 448
37 private let HEIGHT = 160
38 private let VHEIGHT = 236
11 39
12 override func viewDidLoad() { 40 override func viewDidLoad() {
13 super.viewDidLoad() 41 super.viewDidLoad()
14 // Do any additional setup after loading the view. 42
43 UserDefaults.standard.addObserver(self, forKeyPath: "Display_Address", options: .new, context: nil)
44 constructSocket()
45
46 switch AVCaptureDevice.authorizationStatus(for: .video) {
47 case .authorized: // the user has already authorized to access the camera.
48 DispatchQueue.main.async {
49 self.createSession()
50 }
51 case .notDetermined:
52 AVCaptureDevice.requestAccess (for: .video) { (granted) in
53 if granted {
54 print("the user has granted to access the camera")
55 DispatchQueue.main.async {
56 self.createSession ()
57 }
58 } else {
59 print("the user has not granted to access the camera")
60 let dialogMessage = UIAlertController(title: "Attention", message: "Can not work without camera access", preferredStyle: .alert)
61 self.present(dialogMessage, animated: true, completion: nil)
62 }
63 }
64 case .denied:
65 print("the user has denied previously to access the camera.")
66 let dialogMessage = UIAlertController(title: "Attention", message: "Can not work without camera access", preferredStyle: .alert)
67 self.present(dialogMessage, animated: true, completion: nil)
68
69 case .restricted:
70 print("the user can't give camera access due to some restriction.")
71 let dialogMessage = UIAlertController(title: "Attention", message: "Can not work without camera access", preferredStyle: .alert)
72 self.present(dialogMessage, animated: true, completion: nil)
73
74 default:
75 print("something has wrong due to we can't access the camera.")
76 let dialogMessage = UIAlertController(title: "Attention", message: "Can not work without camera access", preferredStyle: .alert)
77 self.present(dialogMessage, animated: true, completion: nil)
78 }
79 }
80
81 override func viewDidAppear(_ animated: Bool) {
82 super.viewDidAppear(animated)
83 prevLayer?.frame.size = cameraView.frame.size
15 } 84 }
16 85
86 func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
17 87
18} 88 let now = CACurrentMediaTime()
89 let freq = (Int)(1 / (now - lastTimeStamp))
90// print ("Elapsed: \(now - lastTimeStamp) - Frequency: \(1 / (now - lastTimeStamp))")
91 lastTimeStamp = now
92
93 guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
94
95 CVPixelBufferLockBaseAddress(pixelBuffer, .readOnly)
96 let bufferWidth = CVPixelBufferGetWidth(pixelBuffer)
97 let bufferHeight = CVPixelBufferGetHeight(pixelBuffer)
98 let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)
99 let kBytesPerPixel = 4
100
101 print("\(bufferWidth) \(bufferHeight) \(bytesPerRow)")
102 guard let baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer) else { return }
103
104 var packet: [UInt8] = [0, 0x12, 0, 0, 0x23, 0, 0, 0, 0, 0]
105 var scratch: [Int] = Array(repeating: 0, count: WIDTH*(2+VHEIGHT))
106
107 let t1 = CACurrentMediaTime()
108
109 // 160 real rows are interleaved with 19 gaps of 4 pixels height on the display
110 // so we create 20 virtual blocks of 8 real and 4 virtual pixels
111 // we overlay VHEIGHT==236 virtual rows on the image and later skip the 4 invisble rows
112 var off = 0
113 for row in 0..<VHEIGHT {
114 let zeile = (Int)(((Double)(row) / (Double)(VHEIGHT)) * (Double)(bufferHeight)) * bytesPerRow
115 for column in 0..<WIDTH {
116 let pixel = kBytesPerPixel * (Int)(((Double)(column) / (Double)(WIDTH)) * (Double)(bufferWidth))
117
118 let red = (Int)(baseAddress.load(fromByteOffset: zeile + pixel + 0, as: UInt8.self)) * 19535
119 let green = (Int)(baseAddress.load(fromByteOffset: zeile + pixel + 1, as: UInt8.self)) * 38470
120 let blue = (Int)(baseAddress.load(fromByteOffset: zeile + pixel + 2, as: UInt8.self)) * 7448
121 //scratch[row * WIDTH + column] = red + blue + green
122 scratch[off] = red + blue + green
123 off += 1
124 }
125 }
126
127 var acc = 0
128 var accv = 0
129
130 for row in 0..<VHEIGHT {
131 for column in 0..<WIDTH {
132 let pixel = scratch[row * WIDTH + column]
133 let bwpixel = (pixel < 0x810000) ? 0 : 0xffffff
134
135 // account for gaps on display (virtual lines 9-12)
136 if (row % 12) < 8 {
137 acc = (acc << 1) + (bwpixel >> 23)
138 accv += 1
139 if accv == 8 {
140 packet.append((UInt8)(acc))
141 acc = 0
142 accv = 0
143 }
144 }
145
146 let err = (pixel - bwpixel) / 42
147
148 func AddSatShift(_ scr: inout Array<Int>, _ X: Int, _ Y: Int, _ SHIFT: Int) {
149 let inner_p = (row + Y) * WIDTH + column + X
150 var r = scr[inner_p] + (err << (16 - SHIFT))
151 if r < 0 {
152 r = 0
153 }
154 if r > 0xffffff {
155 r = 0xffffff
156 }
157 scr[inner_p] = r
158 }
159
160 AddSatShift(&scratch, 0, 1, 13)
161 AddSatShift(&scratch, 0, 2, 14)
162 if (column > 0) {
163 AddSatShift(&scratch, -1, 1, 14)
164 AddSatShift(&scratch, -1, 2, 15)
165 }
166
167 if (column > 1) {
168 AddSatShift(&scratch, -2, 1, 15)
169 AddSatShift(&scratch, -2, 2, 16)
170 }
171
172 if (column < WIDTH - 1) {
173 AddSatShift(&scratch, 1, 0, 13)
174 AddSatShift(&scratch, 1, 1, 14)
175 AddSatShift(&scratch, 1, 2, 15)
176 }
177
178 if (column < WIDTH - 2) {
179 AddSatShift(&scratch, 2, 0, 14)
180 AddSatShift(&scratch, 2, 1, 15)
181 AddSatShift(&scratch, 2, 2, 16)
182 }
183
184 }
185 }
186
187 let t2 = CACurrentMediaTime()
188
189// print("dur \(t2 - t1)")
190 DispatchQueue.main.async {
191 self.frameRateLabel.text = String(format: "%.04f (%d Hz)", t2 - t1, freq)
192 }
193
194 self.connectionUDP?.send(content: packet, completion: NWConnection.SendCompletion.contentProcessed(({ (NWError) in
195 if (NWError == nil) {
196 print("Data was sent to UDP")
197 } else {
198 print("ERROR! Error when data (Type: Data) sending. NWError: \n \(NWError!)")
199 self.constructSocket()
200 }
201 })))
202 }
19 203
204 func createSession() {
205 guard let device = AVCaptureDevice.default(for: AVMediaType.video) else { return }
206 do {
207 input = try AVCaptureDeviceInput(device: device)
208 }
209 catch {
210 print(error)
211 }
212
213 captureSession.sessionPreset = AVCaptureSession.Preset.vga640x480
214 if let input = input {
215 captureSession.addInput(input)
216 }
217
218 prevLayer = AVCaptureVideoPreviewLayer(session: captureSession)
219 prevLayer?.frame.size = cameraView.frame.size
220 prevLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
221
222 cameraView.layer.addSublayer(prevLayer!)
223 captureSession.addOutput(videoDataOutput)
224 captureSession.commitConfiguration()
225
226 videoDataOutput.videoSettings.updateValue(kCVPixelFormatType_32BGRA, forKey: "PixelFormatType")
227 videoDataOutput.setSampleBufferDelegate(self, queue: self.sessionQueue)
228
229 do {
230 try device.lockForConfiguration()
231 device.activeVideoMaxFrameDuration = CMTimeMake(value: 1, timescale: 60)
232 device.activeVideoMinFrameDuration = CMTimeMake(value: 1, timescale: 60)
233 device.unlockForConfiguration()
234 } catch {
235 print(error)
236 }
237
238 let captureConnection = videoDataOutput.connection(with: .video)
239 captureConnection?.isEnabled = true
240 deviceOrientationDidChange(Notification(name: UIDevice.orientationDidChangeNotification))
241 // captureConnection?.videoOrientation = .landscapeRight
242
243 sessionQueue.async { self.captureSession.startRunning() }
244 }
245
246 func cameraWithPosition(position: AVCaptureDevice.Position) -> AVCaptureDevice? {
247 if #available(iOS 11.1, *) {
248 let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera, .builtInTelephotoCamera, .builtInTrueDepthCamera, .builtInWideAngleCamera, ], mediaType: .video, position: position)
249
250 if let device = deviceDiscoverySession.devices.first {
251 return device
252 }
253 else {
254 //add code here
255 }
256 return nil
257 }
258
259 return device
260 }
261
262 func transformOrientation(orientation: UIInterfaceOrientation) -> AVCaptureVideoOrientation {
263 switch orientation {
264 case .landscapeLeft:
265 return .landscapeLeft
266 case .landscapeRight:
267 return .landscapeRight
268 case .portraitUpsideDown:
269 return .portraitUpsideDown
270 default:
271 return .portrait
272 }
273 }
274
275 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
276 if keyPath == "Display_Address" {
277 constructSocket()
278 }
279 }
280
281 func constructSocket() {
282 let defaults = UserDefaults.standard
283 if let ip = defaults.string(forKey: "Display_Address") {
284 hostUDP = NWEndpoint.Host(ip)
285 } else {
286 hostUDP = NWEndpoint.Host("172.23.42.29")
287 // hostUDP = NWEndpoint.Host("84.200.61.9")
288 // hostUDP = NWEndpoint.Host("192.168.178.69")
289 }
290// hostUDP = NWEndpoint.Host("192.168.178.69")
291
292 self.connectionUDP = NWConnection(host: hostUDP!, port: portUDP, using: .udp)
293 self.connectionUDP?.start(queue: .global())
294 }
295
296 @IBAction func switchCameraSide(sender: AnyObject) {
297 let currentCameraInput: AVCaptureInput = captureSession.inputs[0]
298 captureSession.removeInput(currentCameraInput)
299 var newCamera: AVCaptureDevice
300 if (currentCameraInput as! AVCaptureDeviceInput).device.position == .back {
301 newCamera = self.cameraWithPosition(position: .front)!
302 } else {
303 newCamera = self.cameraWithPosition(position: .back)!
304 }
305
306 var newVideoInput: AVCaptureDeviceInput?
307 do{
308 newVideoInput = try AVCaptureDeviceInput(device: newCamera)
309 }
310 catch{
311 print(error)
312 }
313
314 if let newVideoInput = newVideoInput{
315 captureSession.addInput(newVideoInput)
316 deviceOrientationDidChange(Notification(name: UIDevice.orientationDidChangeNotification))
317 }
318 }
319
320 override func viewWillAppear(_ animated: Bool) {
321 super.viewWillAppear(animated)
322
323 NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange),
324 name: UIDevice.orientationDidChangeNotification, object: nil)
325 deviceOrientationDidChange(Notification(name: UIDevice.orientationDidChangeNotification))
326
327 sessionQueue.async { self.captureSession.startRunning() }
328 }
329
330 override func viewWillDisappear(_ animated: Bool) {
331 super.viewWillDisappear(animated)
332
333 sessionQueue.async { self.captureSession.stopRunning() }
334 NotificationCenter.default.removeObserver(self)
335 }
336
337 @objc func deviceOrientationDidChange(_ notification: Notification) {
338 let orientation = UIDevice.current.orientation
339 let captureConnection = videoDataOutput.connection(with: .video)
340
341 if orientation == .landscapeLeft {
342 self.prevLayer?.connection?.videoOrientation = .landscapeRight
343 captureConnection?.videoOrientation = .landscapeRight
344 } else {
345 self.prevLayer?.connection?.videoOrientation = .landscapeLeft
346 captureConnection?.videoOrientation = .landscapeLeft
347 }
348 }
349}