Add AirPlay support
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="EVd-wq-ego">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="EVd-wq-ego">
|
||||
<device id="ipad11_0rounded" orientation="portrait" layout="fullscreen" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
@@ -12,7 +12,7 @@
|
||||
<objects>
|
||||
<viewController id="wb7-af-jn8" customClass="MainFrameViewController" sceneMemberID="viewController">
|
||||
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" indicatorStyle="black" dataMode="prototypes" id="TZj-Lc-M9d" customClass="AppCollectionView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="834" height="1120"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="834" height="1136"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.3333333432674408" green="0.3333333432674408" blue="0.3333333432674408" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="20" minimumInteritemSpacing="20" id="f7l-kG-hJc">
|
||||
@@ -547,6 +547,23 @@ ICAgICAgICAgICAgICA
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="External Display Mode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4Qy-hB-oa5">
|
||||
<rect key="frame" x="16" y="1946" width="170" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.93902439019999995" green="0.9625305918" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="VWB-YB-Ptj" userLabel="External Display Mode">
|
||||
<rect key="frame" x="15" y="1975" width="459" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<segments>
|
||||
<segment title="Stage Manager"/>
|
||||
<segment title="AirPlay"/>
|
||||
</segments>
|
||||
<color key="tintColor" red="0.6716768742" green="0.61711704730000005" blue="0.99902987480000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="selectedSegmentTintColor" red="0.6716768742" green="0.61711704730000005" blue="0.99902987480000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</segmentedControl>
|
||||
</subviews>
|
||||
<color key="backgroundColor" systemColor="viewFlipsideBackgroundColor"/>
|
||||
</view>
|
||||
@@ -559,6 +576,7 @@ ICAgICAgICAgICAgICA
|
||||
<outlet property="btMouseSelector" destination="KMg-3j-F9p" id="W45-AB-sJf"/>
|
||||
<outlet property="cmdToolScreenEdgeSelector" destination="yY7-Sf-Zes" id="fgL-xr-obH"/>
|
||||
<outlet property="codecSelector" destination="aFy-0w-YPe" id="DlU-0l-gwz"/>
|
||||
<outlet property="externalDisplayModeSelector" destination="VWB-YB-Ptj" id="0ak-pc-evb"/>
|
||||
<outlet property="framePacingSelector" destination="7va-uJ-IfD" id="Tbv-s2-u2k"/>
|
||||
<outlet property="framerateSelector" destination="lGK-vl-pdw" id="Kc8-Zv-hdm"/>
|
||||
<outlet property="goBackToStreamViewButton" destination="uSS-ev-IFe" id="2MV-Fl-nIz"/>
|
||||
@@ -607,7 +625,7 @@ ICAgICAgICAgICAgICA
|
||||
<viewControllerLayoutGuide type="bottom" id="YRO-Lg-RCg"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="hGs-BR-t4b">
|
||||
<rect key="frame" x="0.0" y="0.0" width="834" height="1194"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="834" height="1210"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
@@ -647,7 +665,7 @@ ICAgICAgICAgICAgICA
|
||||
<viewControllerLayoutGuide type="bottom" id="vu8-3s-HlY"/>
|
||||
</layoutGuides>
|
||||
<view key="view" multipleTouchEnabled="YES" contentMode="scaleToFill" id="SMn-1j-R3I">
|
||||
<rect key="frame" x="0.0" y="0.0" width="834" height="1194"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="834" height="1210"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" red="0.3333357871" green="0.33332890269999998" blue="0.33333355190000002" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
</view>
|
||||
@@ -669,7 +687,7 @@ ICAgICAgICAgICAgICA
|
||||
<viewControllerLayoutGuide type="bottom" id="YZj-An-sqS"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="le1-tU-NEp">
|
||||
<rect key="frame" x="0.0" y="0.0" width="834" height="1194"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="834" height="1210"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" animating="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="N0D-dj-EuF">
|
||||
@@ -696,7 +714,7 @@ ICAgICAgICAgICAgICA
|
||||
<viewControllerLayoutGuide type="bottom" id="eaS-aj-VtA"/>
|
||||
</layoutGuides>
|
||||
<view key="view" opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="Acw-S4-f8a">
|
||||
<rect key="frame" x="0.0" y="0.0" width="834" height="1194"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="834" height="1210"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view alpha="0.75" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fZU-G0-fgM" userLabel="Toolbar Root View" customClass="ToolBarContainerView">
|
||||
@@ -893,11 +911,11 @@ ICAgICAgICAgICAgICA
|
||||
<viewControllerLayoutGuide type="bottom" id="8ja-wQ-jbJ"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="PlJ-LJ-d1p">
|
||||
<rect key="frame" x="0.0" y="0.0" width="834" height="1194"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="834" height="1210"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView opaque="NO" clearsContextBeforeDrawing="NO" alpha="0.5" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="-1" estimatedSectionHeaderHeight="-1" sectionFooterHeight="-1" estimatedSectionFooterHeight="-1" translatesAutoresizingMaskIntoConstraints="NO" id="BA3-hd-bDp">
|
||||
<rect key="frame" x="0.0" y="44" width="834" height="1150"/>
|
||||
<rect key="frame" x="0.0" y="44" width="834" height="1166"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</tableView>
|
||||
<navigationBar contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="62V-DN-FUk">
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="DL0-L5-LOv">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="DL0-L5-LOv">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
@@ -563,6 +563,23 @@ ICAgICAgICAgICAgIA
|
||||
<color key="tintColor" red="0.6716768742" green="0.61711704730000005" blue="0.99902987480000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="selectedSegmentTintColor" red="0.6716768742" green="0.61711704730000005" blue="0.99902987480000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</segmentedControl>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="External Display Mode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4Qy-hB-oa5">
|
||||
<rect key="frame" x="20" y="1872" width="181" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
|
||||
<color key="textColor" red="0.93902439019999995" green="0.9625305918" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="VWB-YB-Ptj" userLabel="External Display Mode">
|
||||
<rect key="frame" x="19" y="1901" width="450" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<segments>
|
||||
<segment title="Stage Manager"/>
|
||||
<segment title="AirPlay"/>
|
||||
</segments>
|
||||
<color key="tintColor" red="0.6716768742" green="0.61711704730000005" blue="0.99902987480000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="selectedSegmentTintColor" red="0.6716768742" green="0.61711704730000005" blue="0.99902987480000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</segmentedControl>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.12156862745098039" green="0.12941176470588237" blue="0.14117647058823529" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
@@ -575,6 +592,7 @@ ICAgICAgICAgICAgIA
|
||||
<outlet property="btMouseSelector" destination="o4O-hO-teB" id="bLu-uv-yUX"/>
|
||||
<outlet property="cmdToolScreenEdgeSelector" destination="zDR-Ss-JPc" id="cUd-Ot-bZg"/>
|
||||
<outlet property="codecSelector" destination="AbS-CW-fjP" id="ohH-Tc-UzM"/>
|
||||
<outlet property="externalDisplayModeSelector" destination="VWB-YB-Ptj" id="0ak-pc-evb"/>
|
||||
<outlet property="framePacingSelector" destination="d2a-Ka-H2c" id="Ocv-3E-lIm"/>
|
||||
<outlet property="framerateSelector" destination="dLF-qJ-2nY" id="hE3-hk-iwa"/>
|
||||
<outlet property="goBackToStreamViewButton" destination="FqF-bM-afQ" id="Xoj-dC-gEa"/>
|
||||
|
||||
@@ -43,7 +43,8 @@
|
||||
touchMode:(NSInteger)touchMode
|
||||
statsOverlay:(BOOL)statsOverlay
|
||||
allowPortrait:(BOOL)allowPortrait
|
||||
resolutionSelected:(NSInteger)resolutionSelected;
|
||||
resolutionSelected:(NSInteger)resolutionSelected
|
||||
externalDisplayMode:(NSInteger)externalDisplayMode;
|
||||
|
||||
- (NSArray*) getHosts;
|
||||
- (void) updateHost:(TemporaryHost*)host;
|
||||
|
||||
@@ -82,7 +82,8 @@
|
||||
touchMode:(NSInteger)touchMode
|
||||
statsOverlay:(BOOL)statsOverlay
|
||||
allowPortrait:(BOOL)allowPortrait
|
||||
resolutionSelected:(NSInteger)resolutionSelected {
|
||||
resolutionSelected:(NSInteger)resolutionSelected
|
||||
externalDisplayMode:(NSInteger)externalDisplayMode {
|
||||
|
||||
[_managedObjectContext performBlockAndWait:^{
|
||||
Settings* settingsToSave = [self retrieveSettings];
|
||||
@@ -117,7 +118,7 @@
|
||||
settingsToSave.statsOverlay = statsOverlay;
|
||||
settingsToSave.allowPortrait = allowPortrait;
|
||||
settingsToSave.resolutionSelected = [NSNumber numberWithInteger:resolutionSelected];
|
||||
|
||||
settingsToSave.externalDisplayMode = [NSNumber numberWithInteger:externalDisplayMode];
|
||||
[self saveData];
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
@property (nonatomic, retain) NSNumber * pointerVelocityModeDivider;
|
||||
@property (nonatomic, retain) NSString * uniqueId;
|
||||
@property (nonatomic, retain) NSNumber * resolutionSelected;
|
||||
@property (nonatomic, retain) NSNumber * externalDisplayMode;
|
||||
@property (nonatomic) enum {
|
||||
CODEC_PREF_AUTO,
|
||||
CODEC_PREF_H264,
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
self.pointerVelocityModeDivider = settings.pointerVelocityModeDivider;
|
||||
self.allowPortrait = settings.allowPortrait;
|
||||
self.resolutionSelected = settings.resolutionSelected;
|
||||
self.externalDisplayMode = settings.externalDisplayMode;
|
||||
#endif
|
||||
self.uniqueId = settings.uniqueId;
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UIRequiresFullScreen</key>
|
||||
<true/>
|
||||
<false/>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<true/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
<attribute name="btMouseSupport" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="deviceGyroMode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="enableHdr" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="externalDisplayMode" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="framerate" attributeType="Integer 32" defaultValueString="60" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="height" attributeType="Integer 32" defaultValueString="720" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="keyboardToggleFingers" optional="YES" attributeType="Integer 16" defaultValueString="3" usesScalarValueType="NO" syncable="YES"/>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
<attribute name="btMouseSupport" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="deviceGyroMode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="enableHdr" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="externalDisplayMode" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="framerate" attributeType="Integer 32" defaultValueString="60" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="height" attributeType="Integer 32" defaultValueString="720" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="keyboardToggleFingers" optional="YES" attributeType="Integer 16" defaultValueString="3" usesScalarValueType="NO" syncable="YES"/>
|
||||
|
||||
@@ -90,6 +90,11 @@ extern int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size,
|
||||
|
||||
[self reinitializeDisplayLayer];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(reinitializeDisplayLayer)
|
||||
name:@"ScreenChanged"
|
||||
object:nil];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@@ -617,6 +617,7 @@ static NSMutableSet* hostList;
|
||||
}
|
||||
|
||||
- (void) prepareToStreamApp:(TemporaryApp *)app {
|
||||
[self updateResolutionAccordingly];
|
||||
self.revealViewController.isStreaming = true; // tell the revealViewController streaming is started.
|
||||
_streamConfig = [[StreamConfiguration alloc] init];
|
||||
_streamConfig.host = app.host.activeAddress;
|
||||
@@ -634,9 +635,14 @@ static NSMutableSet* hostList;
|
||||
|
||||
_streamConfig.frameRate = [streamSettings.framerate intValue];
|
||||
if (@available(iOS 10.3, *)) {
|
||||
UIWindow *window = UIApplication.sharedApplication.windows.firstObject;
|
||||
NSInteger maximumFramesPerSecond = window.screen.maximumFramesPerSecond;
|
||||
if(UIScreen.screens.count > 1 && streamSettings.externalDisplayMode.intValue == 1){ //AirPlaying
|
||||
maximumFramesPerSecond = UIScreen.screens.lastObject.maximumFramesPerSecond;
|
||||
}
|
||||
// Don't stream more FPS than the display can show
|
||||
if (_streamConfig.frameRate > [UIScreen mainScreen].maximumFramesPerSecond) {
|
||||
_streamConfig.frameRate = (int)[UIScreen mainScreen].maximumFramesPerSecond;
|
||||
if (_streamConfig.frameRate > maximumFramesPerSecond) {
|
||||
_streamConfig.frameRate = (int)maximumFramesPerSecond;
|
||||
Log(LOG_W, @"Clamping FPS to maximum refresh rate: %d", _streamConfig.frameRate);
|
||||
}
|
||||
}
|
||||
@@ -1171,7 +1177,7 @@ static NSMutableSet* hostList;
|
||||
//if([SettingsViewController isLandscapeNow] != _streamConfig.width > _streamConfig.height)
|
||||
//[self simulateSettingsButtonPress]; //force expand setting view if orientation changed since last quit from app.
|
||||
//[self simulateSettingsButtonPress]; //force expand setting view if orientation changed since last quit from app.
|
||||
[self updateResolutionAccordingly];
|
||||
//[self updateResolutionAccordingly];
|
||||
|
||||
// SettingsViewController* settingsViewController = (SettingsViewController*)[self.revealViewController rearViewController];
|
||||
// [settingsViewController updateResolutionTable];
|
||||
@@ -1219,17 +1225,17 @@ static NSMutableSet* hostList;
|
||||
}
|
||||
|
||||
// this will also be called back when device orientation changes
|
||||
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
|
||||
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
|
||||
|
||||
double delayInSeconds = 0.7;
|
||||
// Convert the delay into a dispatch_time_t value
|
||||
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
|
||||
// Perform some task after the delay
|
||||
dispatch_after(delayTime, dispatch_get_main_queue(), ^{// Code to execute after the delay
|
||||
[self updateResolutionAccordingly];
|
||||
});
|
||||
}
|
||||
//- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
|
||||
// [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
|
||||
//
|
||||
// double delayInSeconds = 0.7;
|
||||
// // Convert the delay into a dispatch_time_t value
|
||||
// dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
|
||||
// // Perform some task after the delay
|
||||
// dispatch_after(delayTime, dispatch_get_main_queue(), ^{// Code to execute after the delay
|
||||
// [self updateResolutionAccordingly];
|
||||
// });
|
||||
//}
|
||||
|
||||
-(void) updateResolutionAccordingly {
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
@@ -1240,6 +1246,13 @@ static NSMutableSet* hostList;
|
||||
CGFloat appWindowHeight = CGRectGetHeight(window.frame) * screenScale;
|
||||
CGFloat screenWidthInPoints = CGRectGetWidth([[UIScreen mainScreen] bounds]);
|
||||
CGFloat screenHeightInPoints = CGRectGetHeight([[UIScreen mainScreen] bounds]);
|
||||
|
||||
if(currentSettings.externalDisplayMode.intValue == 1 && UIScreen.screens.count > 1){
|
||||
CGRect bounds = [UIScreen.screens.lastObject bounds];
|
||||
screenScale = [UIScreen.screens.lastObject scale];
|
||||
appWindowWidth = bounds.size.width * screenScale;
|
||||
appWindowHeight = bounds.size.height * screenScale;
|
||||
}
|
||||
|
||||
bool needSwap = false;
|
||||
|
||||
@@ -1398,7 +1411,7 @@ static NSMutableSet* hostList;
|
||||
object: nil];
|
||||
//[self simulateSettingsButtonPress]; //force reload resolution table in the setting
|
||||
//[self simulateSettingsButtonPress];
|
||||
[self updateResolutionAccordingly];
|
||||
//[self updateResolutionAccordingly];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
@property (strong, nonatomic) LayoutOnScreenControlsViewController *layoutOnScreenControlsVC;
|
||||
@property (nonatomic, strong) MainFrameViewController *mainFrameViewController;
|
||||
|
||||
@property (strong, nonatomic) IBOutlet UISegmentedControl *externalDisplayModeSelector;
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
||||
|
||||
@@ -222,6 +222,9 @@ BOOL isCustomResolution(CGSize res) {
|
||||
return true;
|
||||
}
|
||||
|
||||
- (bool)isAirPlayEnabled{
|
||||
return [self.externalDisplayModeSelector selectedSegmentIndex] == 1;
|
||||
}
|
||||
|
||||
- (void)updateResolutionTable{
|
||||
UIWindow *window = UIApplication.sharedApplication.windows.firstObject;
|
||||
@@ -229,6 +232,12 @@ BOOL isCustomResolution(CGSize res) {
|
||||
CGFloat safeAreaWidth = (window.frame.size.width - window.safeAreaInsets.left - window.safeAreaInsets.right) * screenScale;
|
||||
CGFloat appWindowWidth = window.frame.size.width * screenScale;
|
||||
CGFloat appWindowHeight = window.frame.size.height * screenScale;
|
||||
if([self isAirPlayEnabled] && UIScreen.screens.count > 1){
|
||||
CGRect bounds = [UIScreen.screens.lastObject bounds];
|
||||
screenScale = [UIScreen.screens.lastObject scale];
|
||||
appWindowWidth = bounds.size.width * screenScale;
|
||||
appWindowHeight = bounds.size.height * screenScale;
|
||||
}
|
||||
bool needSwapWidthAndHeight = appWindowWidth > appWindowHeight;
|
||||
|
||||
resolutionTable[4] = CGSizeMake(safeAreaWidth, appWindowHeight);
|
||||
@@ -248,7 +257,7 @@ BOOL isCustomResolution(CGSize res) {
|
||||
// this will also be called back when device orientation changes
|
||||
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
|
||||
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
|
||||
double delayInSeconds = 1.0;
|
||||
double delayInSeconds = 0.2;
|
||||
// Convert the delay into a dispatch_time_t value
|
||||
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
|
||||
// Perform some task after the delay
|
||||
@@ -549,6 +558,8 @@ BOOL isCustomResolution(CGSize res) {
|
||||
self.layoutOnScreenControlsVC = [storyboard instantiateViewControllerWithIdentifier:@"LayoutOnScreenControlsViewController"];
|
||||
self.layoutOnScreenControlsVC.modalPresentationStyle = UIModalPresentationFullScreen;
|
||||
}
|
||||
|
||||
[self.externalDisplayModeSelector setSelectedSegmentIndex:currentSettings.externalDisplayMode.integerValue];
|
||||
}
|
||||
|
||||
- (void)slideToSettingsScreenEdgeChanged{
|
||||
@@ -1055,6 +1066,7 @@ BOOL isCustomResolution(CGSize res) {
|
||||
BOOL enableHdr = [self.hdrSelector selectedSegmentIndex] == 1;
|
||||
BOOL allowPortrait = [self.allowPortraitSelector selectedSegmentIndex] == 1;
|
||||
NSInteger resolutionSelected = [self.resolutionSelector selectedSegmentIndex];
|
||||
NSInteger externalDisplayMode = [self.externalDisplayModeSelector selectedSegmentIndex];
|
||||
[dataMan saveSettingsWithBitrate:_bitrate
|
||||
framerate:framerate
|
||||
height:height
|
||||
@@ -1085,7 +1097,8 @@ BOOL isCustomResolution(CGSize res) {
|
||||
touchMode:touchMode
|
||||
statsOverlay:statsOverlay
|
||||
allowPortrait:allowPortrait
|
||||
resolutionSelected:resolutionSelected];
|
||||
resolutionSelected:resolutionSelected
|
||||
externalDisplayMode:externalDisplayMode];
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
|
||||
@@ -54,6 +54,10 @@
|
||||
UIScrollView *_scrollView;
|
||||
BOOL _userIsInteracting;
|
||||
CGSize _keyboardSize;
|
||||
UIWindow *_extWindow;
|
||||
UIView *_renderView;
|
||||
UIWindow *_deviceWindow;
|
||||
dispatch_block_t _delayedRemoveExtScreen;
|
||||
#if !TARGET_OS_TV
|
||||
CustomEdgeSlideGestureRecognizer *_slideToSettingsRecognizer;
|
||||
CustomEdgeSlideGestureRecognizer *_slideToCmdToolRecognizer;
|
||||
@@ -162,6 +166,8 @@
|
||||
[self->_streamView reloadOnScreenControlsRealtimeWith:(ControllerSupport*)_controllerSupport
|
||||
andConfig:(StreamConfiguration*)_streamConfig]; //reload OSC here.
|
||||
[self->_streamView reloadOnScreenButtonViews]; //reload keyboard buttons here. the keyboard button view will be added to the streamframe view instead streamview, the highest layer, which saves a lot of reengineering
|
||||
[self reloadAirPlayConfig];
|
||||
|
||||
//reconfig statsOverlay
|
||||
self->_statsUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f
|
||||
target:self
|
||||
@@ -179,6 +185,29 @@
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
{
|
||||
[super viewDidAppear:animated];
|
||||
|
||||
_deviceWindow = self.view.window;
|
||||
|
||||
if (UIScreen.screens.count > 1 && [self isAirPlayEnabled]) {
|
||||
[self prepExtScreen:UIScreen.screens.lastObject];
|
||||
}
|
||||
else {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.view insertSubview:self->_renderView atIndex:0];
|
||||
});
|
||||
}
|
||||
|
||||
// check to see if external screen is connected/disconnected
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||
selector: @selector(extScreenDidConnect:)
|
||||
name: UIScreenDidConnectNotification
|
||||
object: nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||
selector: @selector(extScreenDidDisconnect:)
|
||||
name: UIScreenDidDisconnectNotification
|
||||
object: nil];
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
[[self revealViewController] setPrimaryViewController:self];
|
||||
@@ -239,7 +268,9 @@
|
||||
_controllerSupport = [[ControllerSupport alloc] initWithConfig:self.streamConfig delegate:self];
|
||||
_inactivityTimer = nil;
|
||||
|
||||
_renderView = (StreamView*)[[UIView alloc] initWithFrame:self.view.frame];
|
||||
_streamView = [[StreamView alloc] initWithFrame:self.view.frame];
|
||||
_renderView.bounds = _streamView.bounds;
|
||||
//[_streamView setupStreamView:_controllerSupport interactionDelegate:self config:self.streamConfig];
|
||||
[self reConfigStreamViewRealtime]; // call this method again to make sure all gestures are configured & added to the superview(self.view), including the gestures added from inside the streamview.
|
||||
|
||||
@@ -281,7 +312,7 @@
|
||||
_tipLabel.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height * 0.9);
|
||||
|
||||
_streamMan = [[StreamManager alloc] initWithConfig:self.streamConfig
|
||||
renderView:_streamView
|
||||
renderView:_renderView
|
||||
connectionCallbacks:self];
|
||||
NSOperationQueue* opQueue = [[NSOperationQueue alloc] init];
|
||||
[opQueue addOperation:_streamMan];
|
||||
@@ -449,8 +480,86 @@
|
||||
_statsUpdateTimer = nil;
|
||||
|
||||
[self.navigationController popToRootViewControllerAnimated:YES];
|
||||
|
||||
_extWindow = nil;
|
||||
}
|
||||
|
||||
// External Screen connected
|
||||
- (void)extScreenDidConnect:(NSNotification *)notification {
|
||||
Log(LOG_I, @"External Screen Connected");
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self prepExtScreen:notification.object];
|
||||
});
|
||||
}
|
||||
|
||||
// External Screen disconnected
|
||||
- (void)extScreenDidDisconnect:(NSNotification *)notification {
|
||||
Log(LOG_I, @"External Screen Disconnected");
|
||||
if(UIScreen.screens.count < 2)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self removeExtScreen];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) isAirPlaying{
|
||||
return _extWindow != nil && _extWindow.hidden == NO;
|
||||
}
|
||||
|
||||
- (BOOL) isAirPlayEnabled{
|
||||
return _settings.externalDisplayMode.intValue == 1;
|
||||
}
|
||||
|
||||
- (void) reloadAirPlayConfig{
|
||||
if (UIScreen.screens.count == 1){return;}
|
||||
if (![self isAirPlaying] && [self isAirPlayEnabled]){
|
||||
[self prepExtScreen:UIScreen.screens.lastObject];
|
||||
}else if ([self isAirPlaying] && ![self isAirPlayEnabled]){
|
||||
[self removeExtScreen];
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare Screen
|
||||
- (void)prepExtScreen:(UIScreen*)extScreen {
|
||||
Log(LOG_I, @"Preparing External Screen");
|
||||
if(![self isAirPlayEnabled]){
|
||||
return;
|
||||
}
|
||||
CGRect frame = extScreen.bounds;
|
||||
extScreen.overscanCompensation = UIScreenOverscanCompensationNone;
|
||||
if(_extWindow==nil){
|
||||
_extWindow = [[UIWindow alloc] initWithFrame:frame];
|
||||
}
|
||||
_extWindow.screen = extScreen;
|
||||
_renderView.bounds = frame;
|
||||
_renderView.frame = frame;
|
||||
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
|
||||
[nc postNotificationName:@"ScreenChanged" object:self];
|
||||
[_extWindow addSubview:_renderView];
|
||||
_extWindow.hidden = NO;
|
||||
}
|
||||
|
||||
- (void)removeExtScreen {
|
||||
Log(LOG_I, @"Removing External Screen");
|
||||
_extWindow.hidden = YES;
|
||||
[self handleViewResize];
|
||||
[self.view insertSubview:_renderView atIndex:0];
|
||||
}
|
||||
|
||||
- (void) handleViewResize{
|
||||
_streamView.bounds = _deviceWindow.bounds;
|
||||
_streamView.frame = _deviceWindow.frame;
|
||||
if(![self isAirPlaying]){
|
||||
_renderView.bounds = _deviceWindow.bounds;
|
||||
_renderView.frame = _deviceWindow.frame;
|
||||
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
|
||||
[nc postNotificationName:@"ScreenChanged" object:self];
|
||||
}
|
||||
[self reConfigStreamViewRealtime];
|
||||
}
|
||||
|
||||
|
||||
// This will fire if the user opens control center or gets a low battery message
|
||||
- (void)applicationWillResignActive:(NSNotification *)notification {
|
||||
if (_inactivityTimer != nil) {
|
||||
@@ -523,6 +632,7 @@
|
||||
// the first frame of video.
|
||||
self->_stageLabel.hidden = YES;
|
||||
self->_tipLabel.hidden = YES;
|
||||
self->_spinner.hidden = YES;
|
||||
|
||||
[self->_streamView showOnScreenControls];
|
||||
|
||||
@@ -864,7 +974,17 @@
|
||||
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
|
||||
|
||||
Log(LOG_I, @"View size changed, terminating stream");
|
||||
// [self returnToMainFrame];
|
||||
|
||||
double delayInSeconds = 0.2;
|
||||
if (_delayedRemoveExtScreen) {
|
||||
dispatch_block_cancel(_delayedRemoveExtScreen);
|
||||
}
|
||||
dispatch_block_t block = dispatch_block_create(0, ^{
|
||||
[self handleViewResize];
|
||||
});
|
||||
_delayedRemoveExtScreen = block;
|
||||
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
|
||||
dispatch_after(delayTime, dispatch_get_main_queue(), block);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -91,6 +91,36 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"4Qy-hB-oa5.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \"External Display Mode\"; ObjectID = \"4Qy-hB-oa5\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "External Display Mode"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "外接显示模式"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "外接显示模式"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "外接显示模式"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"6w5-Md-NpV.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \"Preferred Codec \"; ObjectID = \"6w5-Md-NpV\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
@@ -2191,6 +2221,66 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"VWB-YB-Ptj.segmentTitles[0]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; VWB-YB-Ptj.segmentTitles[0] = \"Stage Manager\"; ObjectID = \"VWB-YB-Ptj\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Stage Manager"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "台前调度"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "台前调度"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "台前调度"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"VWB-YB-Ptj.segmentTitles[1]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; VWB-YB-Ptj.segmentTitles[1] = \"AirPlay\"; ObjectID = \"VWB-YB-Ptj\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "AirPlay"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "隔空播放"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "隔空播放"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "隔空播放"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"WDY-9o-6Hb.segmentTitles[0]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; WDY-9o-6Hb.segmentTitles[0] = \"No\"; ObjectID = \"WDY-9o-6Hb\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
|
||||
@@ -271,6 +271,36 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"4Qy-hB-oa5.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \"External Display Mode\"; ObjectID = \"4Qy-hB-oa5\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "External Display Mode"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "外接显示模式"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "外接显示模式"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "外接显示模式"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"5pN-Sn-SCN.title" : {
|
||||
"comment" : "Class = \"UINavigationItem\"; title = \"Controller & Button Profiles\"; ObjectID = \"5pN-Sn-SCN\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
@@ -2011,6 +2041,66 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"VWB-YB-Ptj.segmentTitles[0]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; VWB-YB-Ptj.segmentTitles[0] = \"Stage Manager\"; ObjectID = \"VWB-YB-Ptj\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Stage Manager"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "台前调度"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "台前调度"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "台前调度"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"VWB-YB-Ptj.segmentTitles[1]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; VWB-YB-Ptj.segmentTitles[1] = \"AirPlay\"; ObjectID = \"VWB-YB-Ptj\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "AirPlay"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "隔空播放"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "隔空播放"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "隔空播放"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"WGf-9d-eAm.segmentTitles[0]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; WGf-9d-eAm.segmentTitles[0] = \"Off\"; ObjectID = \"WGf-9d-eAm\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
|
||||
Reference in New Issue
Block a user