audio: rework bluetooth headset recognition

This commit is contained in:
Gautier Pelloux-Prayer 2016-01-06 17:17:57 +01:00
parent 6ed2bd5726
commit e06564105f
11 changed files with 572 additions and 450 deletions

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9531" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
</dependencies> </dependencies>
<objects> <objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CallOutgoingView"> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CallOutgoingView">
@ -12,6 +12,12 @@
<outlet property="landscapeView" destination="Czn-ec-dh8" id="ZIk-2g-9Qk"/> <outlet property="landscapeView" destination="Czn-ec-dh8" id="ZIk-2g-9Qk"/>
<outlet property="nameLabel" destination="d5s-yP-8VE" id="0VY-HP-ovD"/> <outlet property="nameLabel" destination="d5s-yP-8VE" id="0VY-HP-ovD"/>
<outlet property="portraitView" destination="25" id="26I-da-00C"/> <outlet property="portraitView" destination="25" id="26I-da-00C"/>
<outlet property="routesBluetoothButton" destination="SH1-xD-Agw" id="ifX-Dy-Tcb"/>
<outlet property="routesButton" destination="29K-Sd-aHF" id="MVM-Mb-OWE"/>
<outlet property="routesEarpieceButton" destination="zs4-Zy-FrP" id="TOt-D3-635"/>
<outlet property="routesSpeakerButton" destination="oKz-6p-EAF" id="yIx-qF-Gd7"/>
<outlet property="routesView" destination="iyf-nk-ORJ" id="LBJ-Rm-VUX"/>
<outlet property="speakerButton" destination="G7m-Av-QlR" id="UHW-L2-NDM"/>
<outlet property="view" destination="25" id="26"/> <outlet property="view" destination="25" id="26"/>
</connections> </connections>
</placeholder> </placeholder>
@ -27,7 +33,6 @@
<button opaque="NO" tag="2" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="NFl-sb-0TV" userLabel="headerBar"> <button opaque="NO" tag="2" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="NFl-sb-0TV" userLabel="headerBar">
<rect key="frame" x="0.0" y="0.0" width="375" height="66"/> <rect key="frame" x="0.0" y="0.0" width="375" height="66"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<animations/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="27"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="27"/>
<state key="normal" title="OUTGOING CALL" backgroundImage="color_F.png"> <state key="normal" title="OUTGOING CALL" backgroundImage="color_F.png">
<color key="titleColor" red="1" green="0.36862745099999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="titleColor" red="1" green="0.36862745099999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -37,7 +42,6 @@
<label opaque="NO" userInteractionEnabled="NO" tag="4" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="John Doe" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="19" id="d5s-yP-8VE" userLabel="nameLabel"> <label opaque="NO" userInteractionEnabled="NO" tag="4" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="John Doe" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="19" id="d5s-yP-8VE" userLabel="nameLabel">
<rect key="frame" x="0.0" y="92" width="375" height="52"/> <rect key="frame" x="0.0" y="92" width="375" height="52"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="33"/> <fontDescription key="fontDescription" type="system" pointSize="33"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
@ -45,7 +49,6 @@
<label opaque="NO" userInteractionEnabled="NO" tag="5" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="john.doe@sip.linphone.org" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="8" id="2fa-Ag-3GW" userLabel="addressLabel"> <label opaque="NO" userInteractionEnabled="NO" tag="5" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="john.doe@sip.linphone.org" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="8" id="2fa-Ag-3GW" userLabel="addressLabel">
<rect key="frame" x="4" y="146" width="367" height="34"/> <rect key="frame" x="4" y="146" width="367" height="34"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="18"/> <fontDescription key="fontDescription" type="system" pointSize="18"/>
<color key="textColor" red="1" green="0.36862745099999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="1" green="0.36862745099999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
@ -53,12 +56,84 @@
<imageView userInteractionEnabled="NO" tag="6" contentMode="scaleAspectFit" image="avatar.png" id="bNo-O5-DWh" userLabel="avatarImage" customClass="UIRoundedImageView"> <imageView userInteractionEnabled="NO" tag="6" contentMode="scaleAspectFit" image="avatar.png" id="bNo-O5-DWh" userLabel="avatarImage" customClass="UIRoundedImageView">
<rect key="frame" x="87" y="214" width="200" height="200"/> <rect key="frame" x="87" y="214" width="200" height="200"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<animations/>
<accessibility key="accessibilityConfiguration" label="Contact avatar"> <accessibility key="accessibilityConfiguration" label="Contact avatar">
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/> <accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
<bool key="isElement" value="YES"/> <bool key="isElement" value="YES"/>
</accessibility> </accessibility>
</imageView> </imageView>
<view hidden="YES" tag="37" contentMode="scaleToFill" id="iyf-nk-ORJ" userLabel="routesView">
<rect key="frame" x="94" y="364" width="94" height="198"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" tag="38" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="color_F.png" id="xEp-Iw-uII" userLabel="backgroundColor">
<rect key="frame" x="0.0" y="0.0" width="94" height="198"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
</imageView>
<button opaque="NO" tag="39" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="SH1-xD-Agw" userLabel="routesBluetoothButton" customClass="UIBluetoothButton">
<rect key="frame" x="0.0" y="0.0" width="94" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Bluetooth"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<inset key="titleEdgeInsets" minX="0.0" minY="28" maxX="0.0" maxY="0.0"/>
<state key="normal" image="route_bluetooth_default.png">
<color key="titleColor" red="0.25490196079999999" green="0.28235294119999998" blue="0.30980392159999998" alpha="1" colorSpace="deviceRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="disabled" image="route_bluetooth_disabled.png">
<color key="titleColor" red="0.65098039220000004" green="0.70196078429999997" blue="0.74901960779999999" alpha="1" colorSpace="deviceRGB"/>
</state>
<state key="selected" image="route_bluetooth_selected.png"/>
<state key="highlighted" backgroundImage="color_E.png">
<color key="titleColor" red="0.81176470590000005" green="0.29803921570000003" blue="0.16078431369999999" alpha="1" colorSpace="deviceRGB"/>
</state>
<connections>
<action selector="onRoutesBluetoothClick:" destination="-1" eventType="touchUpInside" id="0bq-3n-xii"/>
</connections>
</button>
<button opaque="NO" tag="40" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="zs4-Zy-FrP" userLabel="routesEarpieceButton">
<rect key="frame" x="0.0" y="66" width="94" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Receiver"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<inset key="titleEdgeInsets" minX="0.0" minY="28" maxX="0.0" maxY="0.0"/>
<state key="normal" image="route_earpiece_default.png">
<color key="titleColor" red="0.25490196079999999" green="0.28235294119999998" blue="0.30980392159999998" alpha="1" colorSpace="deviceRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="disabled" image="route_earpiece_disabled.png">
<color key="titleColor" red="0.65098039220000004" green="0.70196078429999997" blue="0.74901960779999999" alpha="1" colorSpace="deviceRGB"/>
</state>
<state key="selected" image="route_earpiece_selected.png"/>
<state key="highlighted" backgroundImage="color_E.png">
<color key="titleColor" red="0.81176470590000005" green="0.29803921570000003" blue="0.16078431369999999" alpha="1" colorSpace="deviceRGB"/>
</state>
<connections>
<action selector="onRoutesEarpieceClick:" destination="-1" eventType="touchUpInside" id="YRr-Kn-GgV"/>
</connections>
</button>
<button opaque="NO" tag="41" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="oKz-6p-EAF" userLabel="routesSpeakerButton" customClass="UISpeakerButton">
<rect key="frame" x="0.0" y="132" width="94" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<accessibility key="accessibilityConfiguration" label="Speaker"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<inset key="titleEdgeInsets" minX="0.0" minY="28" maxX="0.0" maxY="0.0"/>
<state key="normal" image="route_speaker_default.png">
<color key="titleColor" red="0.25490196079999999" green="0.28235294119999998" blue="0.30980392159999998" alpha="1" colorSpace="deviceRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="disabled" image="route_speaker_disabled.png">
<color key="titleColor" red="0.65098039220000004" green="0.70196078429999997" blue="0.74901960779999999" alpha="1" colorSpace="deviceRGB"/>
</state>
<state key="selected" image="route_speaker_selected.png"/>
<state key="highlighted" backgroundImage="color_E.png">
<color key="titleColor" red="0.81176470590000005" green="0.29803921570000003" blue="0.16078431369999999" alpha="1" colorSpace="deviceRGB"/>
</state>
<connections>
<action selector="onRoutesSpeakerClick:" destination="-1" eventType="touchUpInside" id="g4L-6P-Iqw"/>
</connections>
</button>
</subviews>
</view>
<view tag="7" contentMode="scaleToFill" id="8Qi-Cq-3XH" userLabel="tabBar"> <view tag="7" contentMode="scaleToFill" id="8Qi-Cq-3XH" userLabel="tabBar">
<rect key="frame" x="0.0" y="562" width="375" height="63"/> <rect key="frame" x="0.0" y="562" width="375" height="63"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
@ -66,12 +141,10 @@
<imageView userInteractionEnabled="NO" tag="8" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="color_F.png" id="vyh-Us-8kj" userLabel="backgroundColor"> <imageView userInteractionEnabled="NO" tag="8" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="color_F.png" id="vyh-Us-8kj" userLabel="backgroundColor">
<rect key="frame" x="0.0" y="0.0" width="375" height="63"/> <rect key="frame" x="0.0" y="0.0" width="375" height="63"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<animations/>
</imageView> </imageView>
<button opaque="NO" tag="9" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="26e-Pj-2Oh" userLabel="microButton" customClass="UIMicroButton"> <button opaque="NO" tag="9" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="26e-Pj-2Oh" userLabel="microButton" customClass="UIMicroButton">
<rect key="frame" x="0.0" y="0.0" width="94" height="63"/> <rect key="frame" x="0.0" y="0.0" width="94" height="63"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<animations/>
<accessibility key="accessibilityConfiguration" label="Accept"/> <accessibility key="accessibilityConfiguration" label="Accept"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" image="micro_default.png"> <state key="normal" image="micro_default.png">
@ -84,7 +157,6 @@
<button opaque="NO" tag="10" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="G7m-Av-QlR" userLabel="speakerButton" customClass="UISpeakerButton"> <button opaque="NO" tag="10" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="G7m-Av-QlR" userLabel="speakerButton" customClass="UISpeakerButton">
<rect key="frame" x="94" y="0.0" width="94" height="63"/> <rect key="frame" x="94" y="0.0" width="94" height="63"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<animations/>
<accessibility key="accessibilityConfiguration" label="Accept"/> <accessibility key="accessibilityConfiguration" label="Accept"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" image="speaker_default.png"> <state key="normal" image="speaker_default.png">
@ -94,10 +166,24 @@
<state key="selected" image="speaker_selected.png"/> <state key="selected" image="speaker_selected.png"/>
<state key="highlighted" backgroundImage="color_E.png"/> <state key="highlighted" backgroundImage="color_E.png"/>
</button> </button>
<button hidden="YES" opaque="NO" tag="54" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="29K-Sd-aHF" userLabel="routesButton" customClass="UIToggleButton">
<rect key="frame" x="94" y="0.0" width="94" height="63"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Route"/>
<inset key="titleEdgeInsets" minX="0.0" minY="38" maxX="0.0" maxY="0.0"/>
<state key="normal" image="routes_default.png">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="disabled" image="routes_disabled.png"/>
<state key="selected" image="routes_selected.png"/>
<state key="highlighted" backgroundImage="color_E.png"/>
<connections>
<action selector="onRoutesClick:" destination="-1" eventType="touchUpInside" id="hXX-8a-7M4"/>
</connections>
</button>
<button opaque="NO" tag="11" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="AaM-cH-pvW" userLabel="declineButton"> <button opaque="NO" tag="11" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="AaM-cH-pvW" userLabel="declineButton">
<rect key="frame" x="187" y="0.0" width="188" height="63"/> <rect key="frame" x="187" y="0.0" width="188" height="63"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<animations/>
<accessibility key="accessibilityConfiguration" label="Decline"/> <accessibility key="accessibilityConfiguration" label="Decline"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" image="call_hangup_default.png" backgroundImage="color_D.png"> <state key="normal" image="call_hangup_default.png" backgroundImage="color_D.png">
@ -110,15 +196,12 @@
</connections> </connections>
</button> </button>
</subviews> </subviews>
<animations/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view> </view>
</subviews> </subviews>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view> </view>
</subviews> </subviews>
<animations/>
<color key="backgroundColor" red="1" green="1" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> <color key="backgroundColor" red="1" green="1" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina47"/> <simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina47"/>
<point key="canvasLocation" x="29.5" y="166.5"/> <point key="canvasLocation" x="29.5" y="166.5"/>
@ -134,7 +217,6 @@
<button opaque="NO" tag="2" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="oAv-Cz-FaR" userLabel="headerBar"> <button opaque="NO" tag="2" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="oAv-Cz-FaR" userLabel="headerBar">
<rect key="frame" x="0.0" y="0.0" width="667" height="66"/> <rect key="frame" x="0.0" y="0.0" width="667" height="66"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<animations/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="27"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="27"/>
<state key="normal" title="OUTGOING CALL" backgroundImage="color_F.png"> <state key="normal" title="OUTGOING CALL" backgroundImage="color_F.png">
<color key="titleColor" red="1" green="0.36862745099999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="titleColor" red="1" green="0.36862745099999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -144,7 +226,6 @@
<label opaque="NO" userInteractionEnabled="NO" tag="4" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="John Doe" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="19" id="ubQ-ZN-AhT" userLabel="nameLabel"> <label opaque="NO" userInteractionEnabled="NO" tag="4" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="John Doe" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="19" id="ubQ-ZN-AhT" userLabel="nameLabel">
<rect key="frame" x="298" y="121" width="369" height="37"/> <rect key="frame" x="298" y="121" width="369" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="33"/> <fontDescription key="fontDescription" type="system" pointSize="33"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
@ -152,7 +233,6 @@
<label opaque="NO" userInteractionEnabled="NO" tag="5" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="john.doe@sip.linphone.org" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="8" id="Fj8-Pu-ShI" userLabel="addressLabel"> <label opaque="NO" userInteractionEnabled="NO" tag="5" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="john.doe@sip.linphone.org" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="8" id="Fj8-Pu-ShI" userLabel="addressLabel">
<rect key="frame" x="298" y="166" width="368" height="33"/> <rect key="frame" x="298" y="166" width="368" height="33"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="18"/> <fontDescription key="fontDescription" type="system" pointSize="18"/>
<color key="textColor" red="1" green="0.36862745099999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="textColor" red="1" green="0.36862745099999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
@ -160,12 +240,75 @@
<imageView userInteractionEnabled="NO" tag="6" contentMode="scaleAspectFit" image="avatar.png" id="1ZH-n6-QZ0" userLabel="avatarImage" customClass="UIRoundedImageView"> <imageView userInteractionEnabled="NO" tag="6" contentMode="scaleAspectFit" image="avatar.png" id="1ZH-n6-QZ0" userLabel="avatarImage" customClass="UIRoundedImageView">
<rect key="frame" x="110" y="74" width="180" height="180"/> <rect key="frame" x="110" y="74" width="180" height="180"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<animations/>
<accessibility key="accessibilityConfiguration" label="Contact avatar"> <accessibility key="accessibilityConfiguration" label="Contact avatar">
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/> <accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
<bool key="isElement" value="YES"/> <bool key="isElement" value="YES"/>
</accessibility> </accessibility>
</imageView> </imageView>
<view hidden="YES" tag="37" contentMode="scaleToFill" id="EaW-SR-bqv" userLabel="routesView">
<rect key="frame" x="167" y="72" width="167" height="198"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" tag="38" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="color_F.png" id="Tvo-Jg-0h8" userLabel="backgroundColor">
<rect key="frame" x="0.0" y="0.0" width="167" height="198"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
</imageView>
<button opaque="NO" tag="39" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="N7s-YH-dJQ" userLabel="routesBluetoothButton" customClass="UIBluetoothButton">
<rect key="frame" x="0.0" y="0.0" width="167" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Bluetooth"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<inset key="titleEdgeInsets" minX="0.0" minY="28" maxX="0.0" maxY="0.0"/>
<state key="normal" image="route_bluetooth_default.png">
<color key="titleColor" red="0.25490196079999999" green="0.28235294119999998" blue="0.30980392159999998" alpha="1" colorSpace="deviceRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="disabled" image="route_bluetooth_disabled.png">
<color key="titleColor" red="0.65098039220000004" green="0.70196078429999997" blue="0.74901960779999999" alpha="1" colorSpace="deviceRGB"/>
</state>
<state key="selected" image="route_bluetooth_selected.png"/>
<state key="highlighted" backgroundImage="color_E.png">
<color key="titleColor" red="0.81176470590000005" green="0.29803921570000003" blue="0.16078431369999999" alpha="1" colorSpace="deviceRGB"/>
</state>
</button>
<button opaque="NO" tag="40" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="bg7-Cv-tyO" userLabel="routesEarpieceButton">
<rect key="frame" x="0.0" y="66" width="167" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Receiver"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<inset key="titleEdgeInsets" minX="0.0" minY="28" maxX="0.0" maxY="0.0"/>
<state key="normal" image="route_earpiece_default.png">
<color key="titleColor" red="0.25490196079999999" green="0.28235294119999998" blue="0.30980392159999998" alpha="1" colorSpace="deviceRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="disabled" image="route_earpiece_disabled.png">
<color key="titleColor" red="0.65098039220000004" green="0.70196078429999997" blue="0.74901960779999999" alpha="1" colorSpace="deviceRGB"/>
</state>
<state key="selected" image="route_earpiece_selected.png"/>
<state key="highlighted" backgroundImage="color_E.png">
<color key="titleColor" red="0.81176470590000005" green="0.29803921570000003" blue="0.16078431369999999" alpha="1" colorSpace="deviceRGB"/>
</state>
</button>
<button opaque="NO" tag="41" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="yd8-ed-g8u" userLabel="routesSpeakerButton" customClass="UISpeakerButton">
<rect key="frame" x="0.0" y="132" width="167" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<accessibility key="accessibilityConfiguration" label="Speaker"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<inset key="titleEdgeInsets" minX="0.0" minY="28" maxX="0.0" maxY="0.0"/>
<state key="normal" image="route_speaker_default.png">
<color key="titleColor" red="0.25490196079999999" green="0.28235294119999998" blue="0.30980392159999998" alpha="1" colorSpace="deviceRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="disabled" image="route_speaker_disabled.png">
<color key="titleColor" red="0.65098039220000004" green="0.70196078429999997" blue="0.74901960779999999" alpha="1" colorSpace="deviceRGB"/>
</state>
<state key="selected" image="route_speaker_selected.png"/>
<state key="highlighted" backgroundImage="color_E.png">
<color key="titleColor" red="0.81176470590000005" green="0.29803921570000003" blue="0.16078431369999999" alpha="1" colorSpace="deviceRGB"/>
</state>
</button>
</subviews>
</view>
<view tag="7" contentMode="scaleToFill" id="vJ1-A8-eFV" userLabel="tabBar"> <view tag="7" contentMode="scaleToFill" id="vJ1-A8-eFV" userLabel="tabBar">
<rect key="frame" x="0.0" y="270" width="667" height="63"/> <rect key="frame" x="0.0" y="270" width="667" height="63"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
@ -173,12 +316,10 @@
<imageView userInteractionEnabled="NO" tag="8" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="color_F.png" id="eYb-yI-yVB" userLabel="backgroundColor"> <imageView userInteractionEnabled="NO" tag="8" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="color_F.png" id="eYb-yI-yVB" userLabel="backgroundColor">
<rect key="frame" x="0.0" y="0.0" width="667" height="63"/> <rect key="frame" x="0.0" y="0.0" width="667" height="63"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<animations/>
</imageView> </imageView>
<button opaque="NO" tag="9" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="jLg-1u-ulZ" userLabel="microButton" customClass="UIMicroButton"> <button opaque="NO" tag="9" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="jLg-1u-ulZ" userLabel="microButton" customClass="UIMicroButton">
<rect key="frame" x="0.0" y="0.0" width="167" height="63"/> <rect key="frame" x="0.0" y="0.0" width="167" height="63"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<animations/>
<accessibility key="accessibilityConfiguration" label="Accept"/> <accessibility key="accessibilityConfiguration" label="Accept"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" image="micro_default.png"> <state key="normal" image="micro_default.png">
@ -191,7 +332,6 @@
<button opaque="NO" tag="10" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="5CY-aN-NLX" userLabel="speakerButton" customClass="UISpeakerButton"> <button opaque="NO" tag="10" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="5CY-aN-NLX" userLabel="speakerButton" customClass="UISpeakerButton">
<rect key="frame" x="167" y="0.0" width="167" height="63"/> <rect key="frame" x="167" y="0.0" width="167" height="63"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<animations/>
<accessibility key="accessibilityConfiguration" label="Accept"/> <accessibility key="accessibilityConfiguration" label="Accept"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" image="speaker_default.png"> <state key="normal" image="speaker_default.png">
@ -201,10 +341,21 @@
<state key="selected" image="speaker_selected.png"/> <state key="selected" image="speaker_selected.png"/>
<state key="highlighted" backgroundImage="color_E.png"/> <state key="highlighted" backgroundImage="color_E.png"/>
</button> </button>
<button hidden="YES" opaque="NO" tag="54" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="61B-DK-jZ6" userLabel="routesButton" customClass="UIToggleButton">
<rect key="frame" x="167" y="0.0" width="167" height="63"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<accessibility key="accessibilityConfiguration" label="Route"/>
<inset key="titleEdgeInsets" minX="0.0" minY="38" maxX="0.0" maxY="0.0"/>
<state key="normal" image="routes_default.png">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="disabled" image="routes_disabled.png"/>
<state key="selected" image="routes_selected.png"/>
<state key="highlighted" backgroundImage="color_E.png"/>
</button>
<button opaque="NO" tag="11" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="jfG-HJ-FPI" userLabel="declineButton"> <button opaque="NO" tag="11" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="jfG-HJ-FPI" userLabel="declineButton">
<rect key="frame" x="333" y="0.0" width="334" height="63"/> <rect key="frame" x="333" y="0.0" width="334" height="63"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
<animations/>
<accessibility key="accessibilityConfiguration" label="Decline"/> <accessibility key="accessibilityConfiguration" label="Decline"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" image="call_hangup_default.png" backgroundImage="color_D.png"> <state key="normal" image="call_hangup_default.png" backgroundImage="color_D.png">
@ -217,15 +368,12 @@
</connections> </connections>
</button> </button>
</subviews> </subviews>
<animations/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view> </view>
</subviews> </subviews>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view> </view>
</subviews> </subviews>
<animations/>
<color key="backgroundColor" red="1" green="1" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> <color key="backgroundColor" red="1" green="1" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/> <simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
<simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina47"/> <simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina47"/>
@ -243,6 +391,18 @@
<image name="micro_default.png" width="29" height="37"/> <image name="micro_default.png" width="29" height="37"/>
<image name="micro_disabled.png" width="29" height="37"/> <image name="micro_disabled.png" width="29" height="37"/>
<image name="micro_selected.png" width="29" height="37"/> <image name="micro_selected.png" width="29" height="37"/>
<image name="route_bluetooth_default.png" width="16" height="25"/>
<image name="route_bluetooth_disabled.png" width="16" height="25"/>
<image name="route_bluetooth_selected.png" width="16" height="25"/>
<image name="route_earpiece_default.png" width="23" height="24"/>
<image name="route_earpiece_disabled.png" width="23" height="24"/>
<image name="route_earpiece_selected.png" width="23" height="24"/>
<image name="route_speaker_default.png" width="27" height="25"/>
<image name="route_speaker_disabled.png" width="27" height="25"/>
<image name="route_speaker_selected.png" width="27" height="25"/>
<image name="routes_default.png" width="37" height="25"/>
<image name="routes_disabled.png" width="37" height="25"/>
<image name="routes_selected.png" width="37" height="25"/>
<image name="speaker_default.png" width="27" height="25"/> <image name="speaker_default.png" width="27" height="25"/>
<image name="speaker_disabled.png" width="27" height="25"/> <image name="speaker_disabled.png" width="27" height="25"/>
<image name="speaker_selected.png" width="27" height="25"/> <image name="speaker_selected.png" width="27" height="25"/>

View file

@ -386,7 +386,7 @@
<rect key="frame" x="0.0" y="0.0" width="94" height="198"/> <rect key="frame" x="0.0" y="0.0" width="94" height="198"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
</imageView> </imageView>
<button opaque="NO" tag="39" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="6uv-FV-mUL" userLabel="routesBluetoothButton"> <button opaque="NO" tag="39" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="6uv-FV-mUL" userLabel="routesBluetoothButton" customClass="UIBluetoothButton">
<rect key="frame" x="0.0" y="0.0" width="94" height="66"/> <rect key="frame" x="0.0" y="0.0" width="94" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Bluetooth"/> <accessibility key="accessibilityConfiguration" label="Bluetooth"/>
@ -428,7 +428,7 @@
<action selector="onRoutesEarpieceClick:" destination="-1" eventType="touchUpInside" id="RqY-KM-K7M"/> <action selector="onRoutesEarpieceClick:" destination="-1" eventType="touchUpInside" id="RqY-KM-K7M"/>
</connections> </connections>
</button> </button>
<button opaque="NO" tag="41" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="go9-SC-yzb" userLabel="routesSpeakerButton"> <button opaque="NO" tag="41" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="go9-SC-yzb" userLabel="routesSpeakerButton" customClass="UISpeakerButton">
<rect key="frame" x="0.0" y="132" width="94" height="66"/> <rect key="frame" x="0.0" y="132" width="94" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<accessibility key="accessibilityConfiguration" label="Speaker"/> <accessibility key="accessibilityConfiguration" label="Speaker"/>
@ -979,7 +979,7 @@
<rect key="frame" x="0.0" y="0.0" width="84" height="198"/> <rect key="frame" x="0.0" y="0.0" width="84" height="198"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
</imageView> </imageView>
<button opaque="NO" tag="39" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="uPj-2J-1oA" userLabel="routesBluetoothButton"> <button opaque="NO" tag="39" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="uPj-2J-1oA" userLabel="routesBluetoothButton" customClass="UIBluetoothButton">
<rect key="frame" x="0.0" y="0.0" width="84" height="66"/> <rect key="frame" x="0.0" y="0.0" width="84" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Bluetooth"/> <accessibility key="accessibilityConfiguration" label="Bluetooth"/>
@ -1021,7 +1021,7 @@
<action selector="onRoutesEarpieceClick:" destination="-1" eventType="touchUpInside" id="SlB-O8-JVa"/> <action selector="onRoutesEarpieceClick:" destination="-1" eventType="touchUpInside" id="SlB-O8-JVa"/>
</connections> </connections>
</button> </button>
<button opaque="NO" tag="41" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="dsJ-hG-m4c" userLabel="routesSpeakerButton"> <button opaque="NO" tag="41" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="dsJ-hG-m4c" userLabel="routesSpeakerButton" customClass="UISpeakerButton">
<rect key="frame" x="0.0" y="132" width="84" height="66"/> <rect key="frame" x="0.0" y="132" width="84" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<accessibility key="accessibilityConfiguration" label="Speaker"/> <accessibility key="accessibilityConfiguration" label="Speaker"/>
@ -1155,7 +1155,9 @@
<button hidden="YES" opaque="NO" tag="54" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="mxV-GD-O3N" userLabel="routesButton" customClass="UIToggleButton"> <button hidden="YES" opaque="NO" tag="54" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="mxV-GD-O3N" userLabel="routesButton" customClass="UIToggleButton">
<rect key="frame" x="166" y="0.0" width="84" height="63"/> <rect key="frame" x="166" y="0.0" width="84" height="63"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Route"/> <accessibility key="accessibilityConfiguration" label="Route">
<bool key="isElement" value="YES"/>
</accessibility>
<inset key="titleEdgeInsets" minX="0.0" minY="38" maxX="0.0" maxY="0.0"/> <inset key="titleEdgeInsets" minX="0.0" minY="38" maxX="0.0" maxY="0.0"/>
<state key="normal" image="routes_default.png"> <state key="normal" image="routes_default.png">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/> <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>

View file

@ -428,7 +428,7 @@
<action selector="onRoutesEarpieceClick:" destination="-1" eventType="touchUpInside" id="RqY-KM-K7M"/> <action selector="onRoutesEarpieceClick:" destination="-1" eventType="touchUpInside" id="RqY-KM-K7M"/>
</connections> </connections>
</button> </button>
<button opaque="NO" tag="41" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="go9-SC-yzb" userLabel="routesSpeakerButton"> <button opaque="NO" tag="41" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="go9-SC-yzb" userLabel="routesSpeakerButton" customClass="UISpeakerButton">
<rect key="frame" x="0.0" y="132" width="100" height="66"/> <rect key="frame" x="0.0" y="132" width="100" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<accessibility key="accessibilityConfiguration" label="Speaker"/> <accessibility key="accessibilityConfiguration" label="Speaker"/>
@ -1021,7 +1021,7 @@
<action selector="onRoutesEarpieceClick:" destination="-1" eventType="touchUpInside" id="SlB-O8-JVa"/> <action selector="onRoutesEarpieceClick:" destination="-1" eventType="touchUpInside" id="SlB-O8-JVa"/>
</connections> </connections>
</button> </button>
<button opaque="NO" tag="41" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="dsJ-hG-m4c" userLabel="routesSpeakerButton"> <button opaque="NO" tag="41" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="dsJ-hG-m4c" userLabel="routesSpeakerButton" customClass="UISpeakerButton">
<rect key="frame" x="0.0" y="132" width="100" height="66"/> <rect key="frame" x="0.0" y="132" width="100" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<accessibility key="accessibilityConfiguration" label="Speaker"/> <accessibility key="accessibilityConfiguration" label="Speaker"/>

View file

@ -28,7 +28,13 @@
} }
@property(weak, nonatomic) IBOutlet UIRoundedImageView *avatarImage; @property(weak, nonatomic) IBOutlet UIRoundedImageView *avatarImage;
@property(weak, nonatomic) IBOutlet UILabel *nameLabel; @property(weak, nonatomic) IBOutlet UILabel *nameLabel;
@property(weak, nonatomic) IBOutlet UISpeakerButton *speakerButton;
@property(weak, nonatomic) IBOutlet UILabel *addressLabel; @property(weak, nonatomic) IBOutlet UILabel *addressLabel;
@property(weak, nonatomic) IBOutlet UIToggleButton *routesButton;
@property(weak, nonatomic) IBOutlet UIView *routesView;
@property(weak, nonatomic) IBOutlet UIBluetoothButton *routesBluetoothButton;
@property(weak, nonatomic) IBOutlet UIButton *routesEarpieceButton;
@property(weak, nonatomic) IBOutlet UISpeakerButton *routesSpeakerButton;
- (IBAction)onDeclineClick:(id)sender; - (IBAction)onDeclineClick:(id)sender;

View file

@ -48,6 +48,11 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)viewWillAppear:(BOOL)animated { - (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated]; [super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(bluetoothAvailabilityUpdateEvent:)
name:kLinphoneBluetoothAvailabilityUpdate
object:nil];
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]); LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
if (!call) { if (!call) {
if (![PhoneMainView.instance popCurrentView]) { if (![PhoneMainView.instance popCurrentView]) {
@ -61,6 +66,37 @@ static UICompositeViewDescription *compositeDescription = nil;
ms_free(uri); ms_free(uri);
[_avatarImage setImage:[FastAddressBook imageForAddress:addr thumbnail:NO] bordered:YES withRoundedRadius:YES]; [_avatarImage setImage:[FastAddressBook imageForAddress:addr thumbnail:NO] bordered:YES withRoundedRadius:YES];
} }
[self hideSpeaker:LinphoneManager.instance.bluetoothAvailable];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[NSNotificationCenter.defaultCenter removeObserver:self];
}
- (IBAction)onRoutesBluetoothClick:(id)sender {
[self hideRoutes:TRUE animated:TRUE];
[[LinphoneManager instance] setBluetoothEnabled:TRUE];
}
- (IBAction)onRoutesEarpieceClick:(id)sender {
[self hideRoutes:TRUE animated:TRUE];
[[LinphoneManager instance] setSpeakerEnabled:FALSE];
[[LinphoneManager instance] setBluetoothEnabled:FALSE];
}
- (IBAction)onRoutesSpeakerClick:(id)sender {
[self hideRoutes:TRUE animated:TRUE];
[[LinphoneManager instance] setSpeakerEnabled:TRUE];
}
- (IBAction)onRoutesClick:(id)sender {
if ([_routesView isHidden]) {
[self hideRoutes:FALSE animated:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
} else {
[self hideRoutes:TRUE animated:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
}
} }
- (IBAction)onDeclineClick:(id)sender { - (IBAction)onDeclineClick:(id)sender {
@ -68,6 +104,46 @@ static UICompositeViewDescription *compositeDescription = nil;
if (call) { if (call) {
linphone_core_terminate_call([LinphoneManager getLc], call); linphone_core_terminate_call([LinphoneManager getLc], call);
} }
[PhoneMainView.instance popCurrentView]; if (![PhoneMainView.instance popCurrentView]) {
[PhoneMainView.instance changeCurrentView:DialerView.compositeViewDescription];
}
} }
- (void)hideRoutes:(BOOL)hidden animated:(BOOL)animated {
if (IPAD)
return;
if (hidden) {
[_routesButton setOff];
} else {
[_routesButton setOn];
}
_routesBluetoothButton.selected = LinphoneManager.instance.bluetoothEnabled;
_routesSpeakerButton.selected = LinphoneManager.instance.speakerEnabled;
_routesEarpieceButton.selected = !_routesBluetoothButton.selected && !_routesSpeakerButton.selected;
if (hidden != _routesView.hidden) {
// if (animated) {
// [self hideAnimation:hidden forView:_routesView completion:nil];
// } else {
[_routesView setHidden:hidden];
// }
}
}
- (void)hideSpeaker:(BOOL)hidden {
if (IPAD)
return;
_speakerButton.hidden = hidden;
_routesButton.hidden = !hidden;
}
#pragma mark - Event Functions
- (void)bluetoothAvailabilityUpdateEvent:(NSNotification *)notif {
bool available = [[notif.userInfo objectForKey:@"available"] intValue];
[self hideSpeaker:available];
}
@end @end

View file

@ -73,104 +73,6 @@ static UICompositeViewDescription *compositeDescription = nil;
#pragma mark - ViewController Functions #pragma mark - ViewController Functions
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
UIDevice *device = [UIDevice currentDevice];
device.proximityMonitoringEnabled = YES;
[PhoneMainView.instance setVolumeHidden:TRUE];
hiddenVolume = TRUE;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self disableVideoDisplay:NO];
if (hideControlsTimer != nil) {
[hideControlsTimer invalidate];
hideControlsTimer = nil;
}
if (hiddenVolume) {
[PhoneMainView.instance setVolumeHidden:FALSE];
hiddenVolume = FALSE;
}
if (videoDismissTimer) {
[self dismissVideoActionSheet:videoDismissTimer];
[videoDismissTimer invalidate];
videoDismissTimer = nil;
}
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:kLinphoneCallUpdate object:nil];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(messageReceived:)
name:kLinphoneMessageReceived
object:nil];
[self updateUnreadMessage:FALSE];
// Update on show
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
LinphoneCallState state = (call != NULL) ? linphone_call_get_state(call) : 0;
[self callUpdate:call state:state animated:FALSE];
[self hideRoutes:FALSE];
[self hideOptions:FALSE];
[self hidePad:FALSE];
[self showSpeaker];
[self callDurationUpdate];
[self onCurrentCallChange];
// Set windows (warn memory leaks)
linphone_core_set_native_video_window_id([LinphoneManager getLc], (__bridge void *)(_videoView));
linphone_core_set_native_preview_window_id([LinphoneManager getLc], (__bridge void *)(_videoPreview));
// Enable tap
[singleFingerTap setEnabled:TRUE];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdateEvent:)
name:kLinphoneCallUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(bluetoothAvailabilityUpdateEvent:)
name:kLinphoneBluetoothAvailabilityUpdate
object:nil];
[NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(callDurationUpdate)
userInfo:nil
repeats:YES];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[UIApplication sharedApplication] setIdleTimerDisabled:false];
UIDevice *device = [UIDevice currentDevice];
device.proximityMonitoringEnabled = NO;
[PhoneMainView.instance fullScreen:false];
// Disable tap
[singleFingerTap setEnabled:FALSE];
if (linphone_core_get_calls_nb([LinphoneManager getLc]) == 0) {
// reseting speaker button because no more call
_speakerButton.selected = FALSE;
}
}
- (void)viewDidLoad { - (void)viewDidLoad {
[super viewDidLoad]; [super viewDidLoad];
@ -218,17 +120,120 @@ static UICompositeViewDescription *compositeDescription = nil;
[PhoneMainView.instance.view removeGestureRecognizer:singleFingerTap]; [PhoneMainView.instance.view removeGestureRecognizer:singleFingerTap];
// Remove all observer // Remove all observer
[[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSNotificationCenter defaultCenter] removeObserver:self];
[super viewDidUnload]; [super viewDidUnload];
} }
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self updateUnreadMessage:FALSE];
// Update on show
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
LinphoneCallState state = (call != NULL) ? linphone_call_get_state(call) : 0;
[self callUpdate:call state:state animated:FALSE];
[self hideRoutes:TRUE animated:FALSE];
[self hideOptions:TRUE animated:FALSE];
[self hidePad:TRUE animated:FALSE];
[self hideSpeaker:LinphoneManager.instance.bluetoothAvailable];
[self callDurationUpdate];
[self onCurrentCallChange];
// Set windows (warn memory leaks)
linphone_core_set_native_video_window_id([LinphoneManager getLc], (__bridge void *)(_videoView));
linphone_core_set_native_preview_window_id([LinphoneManager getLc], (__bridge void *)(_videoPreview));
// Enable tap
[singleFingerTap setEnabled:TRUE];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(messageReceived:)
name:kLinphoneMessageReceived
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(bluetoothAvailabilityUpdateEvent:)
name:kLinphoneBluetoothAvailabilityUpdate
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(callUpdateEvent:)
name:kLinphoneCallUpdate
object:nil];
[NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(callDurationUpdate)
userInfo:nil
repeats:YES];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
UIDevice.currentDevice.proximityMonitoringEnabled = YES;
[PhoneMainView.instance setVolumeHidden:TRUE];
hiddenVolume = TRUE;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self disableVideoDisplay:TRUE animated:NO];
if (hideControlsTimer != nil) {
[hideControlsTimer invalidate];
hideControlsTimer = nil;
}
if (hiddenVolume) {
[PhoneMainView.instance setVolumeHidden:FALSE];
hiddenVolume = FALSE;
}
if (videoDismissTimer) {
[self dismissVideoActionSheet:videoDismissTimer];
[videoDismissTimer invalidate];
videoDismissTimer = nil;
}
// Remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[[UIApplication sharedApplication] setIdleTimerDisabled:false];
UIDevice.currentDevice.proximityMonitoringEnabled = NO;
[PhoneMainView.instance fullScreen:false];
// Disable tap
[singleFingerTap setEnabled:FALSE];
if (linphone_core_get_calls_nb([LinphoneManager getLc]) == 0) {
// reseting speaker button because no more call
_speakerButton.selected = FALSE;
}
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation]; [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
[self updateUnreadMessage:NO]; [self updateUnreadMessage:NO];
[self previewTouchLift]; [self previewTouchLift];
[self showStatusBar:!videoShown || (_nameLabel.alpha > 0.f)]; [self hideStatusBar:videoShown && (_nameLabel.alpha == 0.f)];
} }
#pragma mark - #pragma mark - UI modification
- (void)hideSpinnerIndicator:(LinphoneCall *)call {
_videoWaitingForFirstImage.hidden = TRUE;
}
static void hideSpinner(LinphoneCall *call, void *user_data) {
CallView *thiz = (__bridge CallView *)user_data;
[thiz hideSpinnerIndicator:call];
}
- (void)updateBottomBar:(LinphoneCall *)call state:(LinphoneCallState)state { - (void)updateBottomBar:(LinphoneCall *)call state:(LinphoneCallState)state {
LinphoneCore *lc = [LinphoneManager getLc]; LinphoneCore *lc = [LinphoneManager getLc];
@ -273,32 +278,27 @@ static UICompositeViewDescription *compositeDescription = nil;
case LinphoneCallError: case LinphoneCallError:
case LinphoneCallIncoming: case LinphoneCallIncoming:
case LinphoneCallOutgoing: case LinphoneCallOutgoing:
[self hidePad:TRUE]; [self hidePad:TRUE animated:TRUE];
[self hideOptions:TRUE]; [self hideOptions:TRUE animated:TRUE];
[self hideRoutes:TRUE]; [self hideRoutes:TRUE animated:TRUE];
default: default:
break; break;
} }
} }
- (void)bluetoothAvailabilityUpdate:(bool)available {
if (available) {
[self hideSpeaker];
} else {
[self showSpeaker];
}
}
- (void)toggleControls:(id)sender { - (void)toggleControls:(id)sender {
bool controlsHidden = (_bottomBar.alpha == 0.0); bool controlsHidden = (_bottomBar.alpha == 0.0);
if (controlsHidden) { [self hideControls:!controlsHidden sender:sender];
[self showControls:sender];
} else {
[self hideControls:sender];
}
} }
- (void)showControls:(id)sender { - (void)timerHideControls:(id)sender {
[self hideControls:TRUE sender:sender];
}
- (void)hideControls:(BOOL)hidden sender:(id)sender {
if (hidden == videoShown)
return;
if (hideControlsTimer) { if (hideControlsTimer) {
[hideControlsTimer invalidate]; [hideControlsTimer invalidate];
hideControlsTimer = nil; hideControlsTimer = nil;
@ -308,153 +308,94 @@ static UICompositeViewDescription *compositeDescription = nil;
// show controls // show controls
[UIView beginAnimations:nil context:nil]; [UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.35]; [UIView setAnimationDuration:0.35];
_pausedCallsTable.tableView.alpha = _videoCameraSwitch.alpha = _callPauseButton.alpha = 1.0; _pausedCallsTable.tableView.alpha = _videoCameraSwitch.alpha = _callPauseButton.alpha = (hidden ? 0 : 1);
_routesView.alpha = _optionsView.alpha = _numpadView.alpha = _bottomBar.alpha = 1.0; _routesView.alpha = _optionsView.alpha = _numpadView.alpha = _bottomBar.alpha = (hidden ? 1 : 0);
_nameLabel.alpha = _durationLabel.alpha = .8; _nameLabel.alpha = _durationLabel.alpha = (hidden ? 0 : .8);
[self showStatusBar:true]; [self hideStatusBar:hidden];
[UIView commitAnimations]; [UIView commitAnimations];
[PhoneMainView.instance showTabBar:true]; [PhoneMainView.instance showTabBar:!hidden];
if (!hidden) {
// hide controls in 5 sec // hide controls in 5 sec
hideControlsTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 hideControlsTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self target:self
selector:@selector(hideControls:) selector:@selector(timerHideControls:)
userInfo:nil userInfo:nil
repeats:NO]; repeats:NO];
}
} }
} }
- (void)hideControls:(id)sender { - (void)disableVideoDisplay:(BOOL)disabled animated:(BOOL)animation {
if (!videoShown) if (disabled == videoShown && animation)
return; return;
if (hideControlsTimer) { if (!disabled) {
[hideControlsTimer invalidate]; [videoZoomHandler resetZoom];
hideControlsTimer = nil;
} }
if ([[PhoneMainView.instance currentView] equal:CallView.compositeViewDescription]) {
[PhoneMainView.instance showTabBar:false];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
_pausedCallsTable.tableView.alpha = _videoCameraSwitch.alpha = _nameLabel.alpha = _durationLabel.alpha =
_callPauseButton.alpha = 0.0;
_routesView.alpha = _optionsView.alpha = _numpadView.alpha = _bottomBar.alpha = 0.0;
[self showStatusBar:false];
[UIView commitAnimations];
}
}
- (void)enableVideoDisplay:(BOOL)animation {
if (videoShown && animation)
return;
videoShown = true;
[videoZoomHandler resetZoom];
if (animation) { if (animation) {
[UIView beginAnimations:nil context:nil]; [UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0]; [UIView setAnimationDuration:1.0];
} }
[_videoGroup setAlpha:1.0]; [_videoGroup setAlpha:disabled ? 0 : 1];
[self hideControls:nil]; [self hideControls:!disabled sender:nil];
if (animation) { if (animation) {
[UIView commitAnimations]; [UIView commitAnimations];
} }
_videoPreview.hidden = (!linphone_core_self_view_enabled([LinphoneManager getLc])); // only show camera switch button if we have more than 1 camera
_videoCameraSwitch.hidden = !disabled && ([LinphoneManager instance].frontCamId != nil);
if ([LinphoneManager instance].frontCamId != nil) { _videoPreview.hidden = (!disabled && !linphone_core_self_view_enabled([LinphoneManager getLc]));
// only show camera switch button if we have more than 1 camera
[_videoCameraSwitch setHidden:FALSE];
}
[PhoneMainView.instance fullScreen:true];
[PhoneMainView.instance showTabBar:false];
#ifdef TEST_VIDEO_VIEW_CHANGE
[NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:@selector(_debugChangeVideoView)
userInfo:nil
repeats:YES];
#endif
// [self batteryLevelChanged:nil];
[_videoWaitingForFirstImage setHidden:NO];
[_videoWaitingForFirstImage startAnimating];
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
// linphone_call_params_get_used_video_codec return 0 if no video stream enabled
if (call != NULL && linphone_call_params_get_used_video_codec(linphone_call_get_current_params(call))) {
linphone_call_set_next_video_frame_decoded_callback(call, hideSpinner, (__bridge void *)(self));
}
}
- (void)disableVideoDisplay:(BOOL)animation {
if (!videoShown && animation)
return;
videoShown = false;
if (animation) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
}
[_videoGroup setAlpha:0.0];
[PhoneMainView.instance showTabBar:true];
[self showControls:nil];
[_videoCameraSwitch setHidden:TRUE];
if (animation) {
[UIView commitAnimations];
}
if (hideControlsTimer != nil) { if (hideControlsTimer != nil) {
[hideControlsTimer invalidate]; [hideControlsTimer invalidate];
hideControlsTimer = nil; hideControlsTimer = nil;
} }
[PhoneMainView.instance fullScreen:false]; [PhoneMainView.instance fullScreen:!disabled];
[PhoneMainView.instance showTabBar:disabled];
if (!disabled) {
#ifdef TEST_VIDEO_VIEW_CHANGE
[NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:@selector(_debugChangeVideoView)
userInfo:nil
repeats:YES];
#endif
// [self batteryLevelChanged:nil];
[_videoWaitingForFirstImage setHidden:NO];
[_videoWaitingForFirstImage startAnimating];
LinphoneCall *call = linphone_core_get_current_call([LinphoneManager getLc]);
// linphone_call_params_get_used_video_codec return 0 if no video stream enabled
if (call != NULL && linphone_call_params_get_used_video_codec(linphone_call_get_current_params(call))) {
linphone_call_set_next_video_frame_decoded_callback(call, hideSpinner, (__bridge void *)(self));
}
}
} }
- (void)displayVideoCall:(BOOL)animated { - (void)displayVideoCall:(BOOL)animated {
[self enableVideoDisplay:animated]; [self disableVideoDisplay:FALSE animated:animated];
} }
- (void)displayTableCall:(BOOL)animated { - (void)displayTableCall:(BOOL)animated {
[self disableVideoDisplay:animated]; [self disableVideoDisplay:TRUE animated:animated];
} }
- (void)showStatusBar:(BOOL)show { - (void)hideStatusBar:(BOOL)hide {
/* we cannot use [PhoneMainView.instance show]; because it will automatically /* we cannot use [PhoneMainView.instance show]; because it will automatically
resize current view to fill empty space, which will resize video. This is resize current view to fill empty space, which will resize video. This is
indesirable since we do not want to crop/rescale video view */ indesirable since we do not want to crop/rescale video view */
PhoneMainView.instance.mainViewController.statusBarView.hidden = !show; PhoneMainView.instance.mainViewController.statusBarView.hidden = hide;
} }
#pragma mark - Spinner Functions
- (void)hideSpinnerIndicator:(LinphoneCall *)call {
_videoWaitingForFirstImage.hidden = TRUE;
}
static void hideSpinner(LinphoneCall *call, void *user_data) {
CallView *thiz = (__bridge CallView *)user_data;
[thiz hideSpinnerIndicator:call];
}
#pragma mark - UI modification
- (void)callDurationUpdate { - (void)callDurationUpdate {
int duration = linphone_core_get_current_call([LinphoneManager getLc]) int duration = linphone_core_get_current_call([LinphoneManager getLc])
@ -484,111 +425,71 @@ static void hideSpinner(LinphoneCall *call, void *user_data) {
} }
} }
- (void)showPad:(BOOL)animated { - (void)hidePad:(BOOL)hidden animated:(BOOL)animated {
[_numpadButton setOn]; if (hidden) {
if ([_numpadView isHidden]) { [_numpadButton setOff];
} else {
[_numpadButton setOn];
}
if (hidden != _numpadView.hidden) {
if (animated) { if (animated) {
[self showAnimation:_numpadView [self hideAnimation:hidden forView:_numpadView completion:nil];
completion:^(BOOL finished){
}];
} else { } else {
[_numpadView setHidden:FALSE]; [_numpadView setHidden:hidden];
} }
} }
} }
- (void)hidePad:(BOOL)animated { - (void)hideRoutes:(BOOL)hidden animated:(BOOL)animated {
[_numpadButton setOff]; if (IPAD)
if (![_numpadView isHidden]) { return;
if (animated) {
[self hideAnimation:_numpadView
completion:^(BOOL finished){
}];
} else {
[_numpadView setHidden:TRUE];
}
}
}
- (void)showRoutes:(BOOL)animated { if (hidden) {
if (![LinphoneManager runningOnIpad]) {
[_routesButton setOn];
[_routesBluetoothButton setSelected:[[LinphoneManager instance] bluetoothEnabled]];
[_routesSpeakerButton setSelected:[[LinphoneManager instance] speakerEnabled]];
[_routesEarpieceButton setSelected:!([[LinphoneManager instance] bluetoothEnabled] ||
[[LinphoneManager instance] speakerEnabled])];
if ([_routesView isHidden]) {
if (animated) {
[self showAnimation:_routesView
completion:^(BOOL finished){
}];
} else {
[_routesView setHidden:FALSE];
}
}
}
}
- (void)hideRoutes:(BOOL)animated {
if (![LinphoneManager runningOnIpad]) {
[_routesButton setOff]; [_routesButton setOff];
if (![_routesView isHidden]) { } else {
if (animated) { [_routesButton setOn];
[self hideAnimation:_routesView
completion:^(BOOL finished){
}];
} else {
[_routesView setHidden:TRUE];
}
}
} }
}
- (void)showOptions:(BOOL)animated { _routesBluetoothButton.selected = LinphoneManager.instance.bluetoothEnabled;
[_optionsButton setOn]; _routesSpeakerButton.selected = LinphoneManager.instance.speakerEnabled;
if ([_optionsView isHidden]) { _routesEarpieceButton.selected = !_routesBluetoothButton.selected && !_routesSpeakerButton.selected;
if (hidden != _routesView.hidden) {
if (animated) { if (animated) {
[self showAnimation:_optionsView [self hideAnimation:hidden forView:_routesView completion:nil];
completion:^(BOOL finished){
}];
} else { } else {
[_optionsView setHidden:FALSE]; [_routesView setHidden:hidden];
} }
} }
} }
- (void)hideOptions:(BOOL)animated { - (void)hideOptions:(BOOL)hidden animated:(BOOL)animated {
[_optionsButton setOff]; if (hidden) {
if (![_optionsView isHidden]) { [_optionsButton setOff];
} else {
[_optionsButton setOn];
}
if (hidden != _optionsView.hidden) {
if (animated) { if (animated) {
[self hideAnimation:_optionsView [self hideAnimation:hidden forView:_optionsView completion:nil];
completion:^(BOOL finished){
}];
} else { } else {
[_optionsView setHidden:TRUE]; [_optionsView setHidden:hidden];
} }
} }
} }
- (void)showSpeaker { - (void)hideSpeaker:(BOOL)hidden {
if (![LinphoneManager runningOnIpad]) { if (IPAD)
[_speakerButton setHidden:FALSE]; return;
[_routesButton setHidden:TRUE]; _speakerButton.hidden = hidden;
} _routesButton.hidden = !hidden;
}
- (void)hideSpeaker {
if (![LinphoneManager runningOnIpad]) {
[_speakerButton setHidden:TRUE];
[_routesButton setHidden:FALSE];
}
} }
#pragma mark - Event Functions #pragma mark - Event Functions
- (void)bluetoothAvailabilityUpdateEvent:(NSNotification *)notif { - (void)bluetoothAvailabilityUpdateEvent:(NSNotification *)notif {
bool available = [[notif.userInfo objectForKey:@"available"] intValue]; bool available = [[notif.userInfo objectForKey:@"available"] intValue];
[self bluetoothAvailabilityUpdate:available]; [self hideSpeaker:available];
} }
- (void)callUpdateEvent:(NSNotification *)notif { - (void)callUpdateEvent:(NSNotification *)notif {
@ -774,9 +675,9 @@ static void hideSpinner(LinphoneCall *call, void *user_data) {
- (IBAction)onNumpadClick:(id)sender { - (IBAction)onNumpadClick:(id)sender {
if ([_numpadView isHidden]) { if ([_numpadView isHidden]) {
[self showPad:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]]; [self hidePad:FALSE animated:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
} else { } else {
[self hidePad:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]]; [self hidePad:TRUE animated:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
} }
} }
@ -786,31 +687,31 @@ static void hideSpinner(LinphoneCall *call, void *user_data) {
} }
- (IBAction)onRoutesBluetoothClick:(id)sender { - (IBAction)onRoutesBluetoothClick:(id)sender {
[self hideRoutes:TRUE]; [self hideRoutes:TRUE animated:TRUE];
[[LinphoneManager instance] setBluetoothEnabled:TRUE]; [[LinphoneManager instance] setBluetoothEnabled:TRUE];
} }
- (IBAction)onRoutesEarpieceClick:(id)sender { - (IBAction)onRoutesEarpieceClick:(id)sender {
[self hideRoutes:TRUE]; [self hideRoutes:TRUE animated:TRUE];
[[LinphoneManager instance] setSpeakerEnabled:FALSE]; [[LinphoneManager instance] setSpeakerEnabled:FALSE];
[[LinphoneManager instance] setBluetoothEnabled:FALSE]; [[LinphoneManager instance] setBluetoothEnabled:FALSE];
} }
- (IBAction)onRoutesSpeakerClick:(id)sender { - (IBAction)onRoutesSpeakerClick:(id)sender {
[self hideRoutes:TRUE]; [self hideRoutes:TRUE animated:TRUE];
[[LinphoneManager instance] setSpeakerEnabled:TRUE]; [[LinphoneManager instance] setSpeakerEnabled:TRUE];
} }
- (IBAction)onRoutesClick:(id)sender { - (IBAction)onRoutesClick:(id)sender {
if ([_routesView isHidden]) { if ([_routesView isHidden]) {
[self showRoutes:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]]; [self hideRoutes:FALSE animated:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
} else { } else {
[self hideRoutes:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]]; [self hideRoutes:TRUE animated:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
} }
} }
- (IBAction)onOptionsTransferClick:(id)sender { - (IBAction)onOptionsTransferClick:(id)sender {
[self hideOptions:TRUE]; [self hideOptions:TRUE animated:TRUE];
// Go to dialer view // Go to dialer view
DialerView *view = VIEW(DialerView); DialerView *view = VIEW(DialerView);
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription]; [PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
@ -821,7 +722,7 @@ static void hideSpinner(LinphoneCall *call, void *user_data) {
} }
- (IBAction)onOptionsAddClick:(id)sender { - (IBAction)onOptionsAddClick:(id)sender {
[self hideOptions:TRUE]; [self hideOptions:TRUE animated:TRUE];
// Go to dialer view // Go to dialer view
DialerView *view = VIEW(DialerView); DialerView *view = VIEW(DialerView);
[PhoneMainView.instance changeCurrentView:view.compositeViewDescription]; [PhoneMainView.instance changeCurrentView:view.compositeViewDescription];
@ -831,9 +732,9 @@ static void hideSpinner(LinphoneCall *call, void *user_data) {
- (IBAction)onOptionsClick:(id)sender { - (IBAction)onOptionsClick:(id)sender {
if ([_optionsView isHidden]) { if ([_optionsView isHidden]) {
[self showOptions:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]]; [self hideOptions:FALSE animated:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
} else { } else {
[self hideOptions:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]]; [self hideOptions:TRUE animated:[[LinphoneManager instance] lpConfigBoolForKey:@"animations_preference"]];
} }
} }
@ -843,27 +744,8 @@ static void hideSpinner(LinphoneCall *call, void *user_data) {
#pragma mark - Animation #pragma mark - Animation
- (void)showAnimation:(UIView *)target completion:(void (^)(BOOL finished))completion { - (void)hideAnimation:(BOOL)hidden forView:(UIView *)target completion:(void (^)(BOOL finished))completion {
CGRect frame = target.frame; if (hidden) {
int original_y = frame.origin.y;
frame.origin.y = self.view.frame.size.height;
target.frame = frame;
frame.origin.y = original_y;
target.hidden = NO;
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
target.frame = frame;
}
completion:^(BOOL finished) {
target.frame = frame; // in case application did not finish
completion(finished);
}];
}
- (void)hideAnimation:(UIView *)target completion:(void (^)(BOOL finished))completion {
int original_y = target.frame.origin.y; int original_y = target.frame.origin.y;
CGRect newFrame = target.frame; CGRect newFrame = target.frame;
newFrame.origin.y = self.view.frame.size.height; newFrame.origin.y = self.view.frame.size.height;
@ -878,8 +760,29 @@ static void hideSpinner(LinphoneCall *call, void *user_data) {
originFrame.origin.y = original_y; originFrame.origin.y = original_y;
target.hidden = YES; target.hidden = YES;
target.frame = originFrame; target.frame = originFrame;
completion(finished); if (completion)
completion(finished);
}]; }];
} else {
CGRect frame = target.frame;
int original_y = frame.origin.y;
frame.origin.y = self.view.frame.size.height;
target.frame = frame;
frame.origin.y = original_y;
target.hidden = NO;
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
target.frame = frame;
}
completion:^(BOOL finished) {
target.frame = frame; // in case application did not finish
if (completion)
completion(finished);
}];
}
} }
#pragma mark - Bounce #pragma mark - Bounce

View file

@ -47,11 +47,6 @@
#define LINPHONE_LOGS_MAX_ENTRY 5000 #define LINPHONE_LOGS_MAX_ENTRY 5000
static void audioRouteChangeListenerCallback(void *inUserData, // 1
AudioSessionPropertyID inPropertyID, // 2
UInt32 inPropertyValueSize, // 3
const void *inPropertyValue // 4
);
static LinphoneCore *theLinphoneCore = nil; static LinphoneCore *theLinphoneCore = nil;
static LinphoneManager *theLinphoneManager = nil; static LinphoneManager *theLinphoneManager = nil;
@ -256,11 +251,10 @@ struct codec_name_pref_table codec_pref_table[] = {{"speex", 8000, "speex_8k_pre
- (id)init { - (id)init {
if ((self = [super init])) { if ((self = [super init])) {
AudioSessionInitialize(NULL, NULL, NULL, NULL); AudioSessionInitialize(NULL, NULL, NULL, NULL);
OSStatus lStatus = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, [[NSNotificationCenter defaultCenter] addObserver:self
audioRouteChangeListenerCallback, (__bridge void *)(self)); selector:@selector(audioRouteChangeListenerCallback2:)
if (lStatus) { name:AVAudioSessionRouteChangeNotification
LOGE(@"cannot register route change handler [%ld]", lStatus); object:nil];
}
NSString *path = [[NSBundle mainBundle] pathForResource:@"msg" ofType:@"wav"]; NSString *path = [[NSBundle mainBundle] pathForResource:@"msg" ofType:@"wav"];
self.messagePlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:path] error:nil]; self.messagePlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:path] error:nil];
@ -298,15 +292,7 @@ struct codec_name_pref_table codec_pref_table[] = {{"speex", 8000, "speex_8k_pre
} }
- (void)dealloc { - (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
OSStatus lStatus = AudioSessionRemovePropertyListenerWithUserData(
kAudioSessionProperty_AudioRouteChange, audioRouteChangeListenerCallback, (__bridge void *)(self));
if (lStatus) {
LOGE(@"cannot un register route change handler [%ld]", lStatus);
}
[[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:kLinphoneGlobalStateUpdate];
[[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:kLinphoneConfiguringStateUpdate];
} }
- (void)silentPushFailed:(NSTimer *)timer { - (void)silentPushFailed:(NSTimer *)timer {
@ -713,7 +699,9 @@ static void linphone_iphone_display_status(struct _LinphoneCore *lc, const char
if (linphone_core_get_calls_nb(theLinphoneCore) == 0) { if (linphone_core_get_calls_nb(theLinphoneCore) == 0) {
[self setSpeakerEnabled:FALSE]; [self setSpeakerEnabled:FALSE];
[self removeCTCallCenterCb]; [self removeCTCallCenterCb];
bluetoothAvailable = FALSE; // disable this because I don't find anygood reason for it: bluetoothAvailable = FALSE;
// furthermore it introduces a bug when calling multiple times since route may not be
// reconfigured between cause leading to bluetooth being disabled while it should not
bluetoothEnabled = FALSE; bluetoothEnabled = FALSE;
/*IOS specific*/ /*IOS specific*/
linphone_core_start_dtmf_stream(theLinphoneCore); linphone_core_start_dtmf_stream(theLinphoneCore);
@ -1800,69 +1788,76 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
OSStatus lStatus = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &lNewRouteSize, &lNewRoute); OSStatus lStatus = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &lNewRouteSize, &lNewRoute);
if (!lStatus && lNewRouteSize > 0) { if (!lStatus && lNewRouteSize > 0) {
NSString *route = (__bridge NSString *)lNewRoute; NSString *route = (__bridge NSString *)lNewRoute;
notallow = [route isEqualToString:@"Headset"] || [route isEqualToString:@"Headphone"] || notallow = [route containsString:@"Heads"] || [route isEqualToString:@"Lineout"] || IPAD;
[route isEqualToString:@"HeadphonesAndMicrophone"] || [route isEqualToString:@"HeadsetInOut"] ||
[route isEqualToString:@"Lineout"] || IPAD;
CFRelease(lNewRoute); CFRelease(lNewRoute);
} }
return !notallow; return !notallow;
} }
static void audioRouteChangeListenerCallback(void *inUserData, // 1 - (void)audioRouteChangeListenerCallback2:(NSNotification *)notif {
AudioSessionPropertyID inPropertyID, // 2 // there is at least one bug when you disconnect an audio bluetooth headset
UInt32 inPropertyValueSize, // 3 // since we only get notification of route having changed, we cannot tell if that is due to:
const void *inPropertyValue // 4 // -bluetooth headset disconnected or
) { // -user wanted to use earpiece
if (inPropertyID != kAudioSessionProperty_AudioRouteChange) // the only thing we can assume is that when we lost a device, it must be a bluetooth one (strong hypothesis though)
return; // 5 if ([[notif.userInfo valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue] ==
LinphoneManager *lm = (__bridge LinphoneManager *)inUserData; AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
bluetoothAvailable = NO;
}
bool speakerEnabled = false; CFStringRef newRoute = CFSTR("Unknown");
CFStringRef lNewRoute = CFSTR("Unknown"); UInt32 newRouteSize = sizeof(newRoute);
UInt32 lNewRouteSize = sizeof(lNewRoute);
OSStatus lStatus = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &lNewRouteSize, &lNewRoute); OSStatus status = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &newRouteSize, &newRoute);
if (!lStatus && lNewRouteSize > 0) { if (!status && newRouteSize > 0) {
NSString *route = (__bridge NSString *)lNewRoute; NSString *route = (__bridge NSString *)newRoute;
LOGI(@"Current audio route is [%s]", [route UTF8String]); LOGI(@"Current audio route is [%s]", [route UTF8String]);
speakerEnabled = [route isEqualToString:@"Speaker"] || [route isEqualToString:@"SpeakerAndMicrophone"]; speakerEnabled = [route isEqualToString:@"Speaker"] || [route isEqualToString:@"SpeakerAndMicrophone"];
if (!IPAD && [route isEqualToString:@"HeadsetBT"] && !speakerEnabled) { if (!IPAD && [route isEqualToString:@"HeadsetBT"] && !speakerEnabled) {
lm.bluetoothEnabled = TRUE; bluetoothAvailable = TRUE;
lm.bluetoothAvailable = TRUE; bluetoothEnabled = TRUE;
NSDictionary *dict = [NSDictionary
dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:lm.bluetoothAvailable], @"available", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneBluetoothAvailabilityUpdate
object:lm
userInfo:dict];
} else { } else {
lm.bluetoothEnabled = FALSE; bluetoothEnabled = FALSE;
} }
CFRelease(lNewRoute); NSDictionary *dict =
} [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:bluetoothAvailable], @"available", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneBluetoothAvailabilityUpdate
if (speakerEnabled != lm.speakerEnabled) { // Reforce value object:self
lm.speakerEnabled = lm.speakerEnabled; userInfo:dict];
CFRelease(newRoute);
} }
} }
- (void)setSpeakerEnabled:(BOOL)enable { - (void)setSpeakerEnabled:(BOOL)enable {
OSStatus ret;
speakerEnabled = enable; speakerEnabled = enable;
UInt32 override = kAudioSessionUnspecifiedError;
if (enable && [self allowSpeaker]) { if (!enable && bluetoothAvailable) {
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; UInt32 bluetoothInputOverride = bluetoothEnabled;
AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), ret = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,
&audioRouteOverride); sizeof(bluetoothInputOverride), &bluetoothInputOverride);
bluetoothEnabled = FALSE; // if setting bluetooth failed, it must be because the device is not available
} else { // anymore (disconnected), so deactivate bluetooth.
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_None; if (ret != kAudioSessionNoError) {
AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), bluetoothAvailable = bluetoothEnabled = FALSE;
&audioRouteOverride); }
} }
if (bluetoothAvailable) { if (override != kAudioSessionNoError) {
UInt32 bluetoothInputOverride = bluetoothEnabled; if (enable && [self allowSpeaker]) {
AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryEnableBluetoothInput, override = kAudioSessionOverrideAudioRoute_Speaker;
sizeof(bluetoothInputOverride), &bluetoothInputOverride); ret = AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(override), &override);
bluetoothEnabled = FALSE;
} else {
override = kAudioSessionOverrideAudioRoute_None;
ret = AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(override), &override);
}
}
if (ret != kAudioSessionNoError) {
LOGE(@"Failed to change audio route: err %d", ret);
} }
} }

View file

@ -41,7 +41,7 @@
<action selector="onHistoryClick:" destination="-1" eventType="touchUpInside" id="22"/> <action selector="onHistoryClick:" destination="-1" eventType="touchUpInside" id="22"/>
</connections> </connections>
</button> </button>
<button opaque="NO" tag="3" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="8" userLabel="contactsButton" customClass="UIIconButton"> <button opaque="NO" tag="3" contentMode="scaleToFill" selected="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="8" userLabel="contactsButton" customClass="UIIconButton">
<rect key="frame" x="90" y="0.0" width="90" height="66"/> <rect key="frame" x="90" y="0.0" width="90" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<accessibility key="accessibilityConfiguration" label="Contacts"/> <accessibility key="accessibilityConfiguration" label="Contacts"/>

View file

@ -39,36 +39,13 @@ static void audioRouteChangeListenerCallback(void *inUserData, // 1
[button update]; [button update];
} }
- (void)initUISpeakerButton { INIT_WITH_COMMON {
AudioSessionInitialize(NULL, NULL, NULL, NULL); AudioSessionInitialize(NULL, NULL, NULL, NULL);
OSStatus lStatus = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, OSStatus lStatus = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange,
audioRouteChangeListenerCallback, (__bridge void *)(self)); audioRouteChangeListenerCallback, (__bridge void *)(self));
if (lStatus) { if (lStatus) {
LOGE(@"cannot register route change handler [%ld]", lStatus); LOGE(@"cannot register route change handler [%ld]", lStatus);
} }
}
- (id)init {
self = [super init];
if (self) {
[self initUISpeakerButton];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self initUISpeakerButton];
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder];
if (self) {
[self initUISpeakerButton];
}
return self; return self;
} }

View file

@ -9,3 +9,6 @@
#import "Log.h" #import "Log.h"
#import "Utils.h" #import "Utils.h"
#import "UISpeakerButton.h"
#import "UIBluetoothButton.h"

@ -1 +1 @@
Subproject commit 218db02a1ab4590d31032b4cbce25b5c34d508e7 Subproject commit 60708a53ab17ccb5084f3ffcbc288edbb5bd3633