Procházet zdrojové kódy

AudioMiniPlayer: Initial

This add a new audio mini player according to the new design.
For now, we will use the same player for audio and video.

(closes #164)
Soomin Lee před 6 roky
rodič
revize
c797a1dea5
26 změnil soubory, kde provedl 494 přidání a 267 odebrání
  1. 168 0
      Resources/Xib/MiniPlayer/AudioMiniPlayer.xib
  2. 2 0
      Resources/en.lproj/Localizable.strings
  3. 171 0
      Sources/MiniPlayer/AudioMiniPlayer.swift
  4. 17 0
      Sources/MiniPlayer/MiniPlayer.swift
  5. 0 21
      Sources/VLCMiniPlaybackView.h
  6. 0 234
      Sources/VLCMiniPlaybackView.m
  7. 6 6
      Sources/VLCPlayerDisplayController.m
  8. 30 6
      VLC.xcodeproj/project.pbxproj
  9. 6 0
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/Contents.json
  10. 23 0
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniNext.imageset/Contents.json
  11. binární
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniNext.imageset/next@1x.png
  12. binární
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniNext.imageset/next@2x.png
  13. binární
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniNext.imageset/next@3x.png
  14. 23 0
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPause.imageset/Contents.json
  15. binární
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPause.imageset/pause@1x.png
  16. binární
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPause.imageset/pause@2x.png
  17. binární
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPause.imageset/pause@3x.png
  18. 23 0
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPlay.imageset/Contents.json
  19. binární
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPlay.imageset/play@1x.png
  20. binární
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPlay.imageset/play@2x.png
  21. binární
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPlay.imageset/play@3x.png
  22. 23 0
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPrev.imageset/Contents.json
  23. binární
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPrev.imageset/prev@1x.png
  24. binární
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPrev.imageset/prev@2x.png
  25. binární
      vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPrev.imageset/prev@3x.png
  26. 2 0
      vlc-ios/VLC-iOS-Bridging-Header.h

+ 168 - 0
Resources/Xib/MiniPlayer/AudioMiniPlayer.xib

@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="AudioMiniPlayer" customModule="VLC">
+            <connections>
+                <outlet property="artistLabel" destination="cVn-oI-gin" id="i0Q-YH-XOJ"/>
+                <outlet property="artworkImageView" destination="kd1-oF-bvh" id="2vA-3k-DNW"/>
+                <outlet property="audioMiniPlayer" destination="uF1-VS-Gss" id="KY2-QZ-jcK"/>
+                <outlet property="nextButton" destination="eyt-Pj-hU6" id="bWI-0V-wbd"/>
+                <outlet property="playPauseButton" destination="2Kp-xd-t2N" id="gXw-IZ-eUx"/>
+                <outlet property="previousButton" destination="Hmp-0g-6lI" id="mbs-Td-8nH"/>
+                <outlet property="progressBarView" destination="IcU-Lc-kf0" id="2nw-wK-b2u"/>
+                <outlet property="titleLabel" destination="aAs-Lc-dt8" id="Ze5-Us-djK"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" restorationIdentifier="AudioMiniPlayer" id="uF1-VS-Gss" userLabel="AudioMiniPlayer">
+            <rect key="frame" x="0.0" y="0.0" width="360" height="56"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <subviews>
+                <stackView opaque="NO" contentMode="scaleToFill" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="ciB-dn-lxu" userLabel="Mini Player Content Stack View">
+                    <rect key="frame" x="8" y="8" width="344" height="40"/>
+                    <subviews>
+                        <stackView opaque="NO" contentMode="scaleToFill" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="KRl-hk-ICS" userLabel="Info Stack View">
+                            <rect key="frame" x="0.0" y="0.0" width="209" height="40"/>
+                            <subviews>
+                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="vlc-xmas" translatesAutoresizingMaskIntoConstraints="NO" id="kd1-oF-bvh" userLabel="Art">
+                                    <rect key="frame" x="0.0" y="0.0" width="40" height="40"/>
+                                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                    <constraints>
+                                        <constraint firstAttribute="height" constant="40" id="08A-CV-78c"/>
+                                        <constraint firstAttribute="width" constant="40" id="TC8-7g-6yK"/>
+                                        <constraint firstAttribute="width" secondItem="kd1-oF-bvh" secondAttribute="height" multiplier="1:1" id="nan-PR-L4K"/>
+                                    </constraints>
+                                </imageView>
+                                <stackView opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="800" axis="vertical" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="oUj-fd-nuu" userLabel="InfoStackView">
+                                    <rect key="frame" x="52" y="0.0" width="157" height="40"/>
+                                    <subviews>
+                                        <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="rRG-rj-ixk">
+                                            <rect key="frame" x="0.0" y="0.0" width="157" height="34.5"/>
+                                            <subviews>
+                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aAs-Lc-dt8" userLabel="Title">
+                                                    <rect key="frame" x="0.0" y="0.0" width="157" height="20"/>
+                                                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                                    <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                                    <nil key="highlightedColor"/>
+                                                </label>
+                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cVn-oI-gin" userLabel="Artist">
+                                                    <rect key="frame" x="0.0" y="20" width="157" height="14.5"/>
+                                                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                                    <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                                                    <color key="textColor" cocoaTouchSystemColor="lightTextColor"/>
+                                                    <nil key="highlightedColor"/>
+                                                </label>
+                                            </subviews>
+                                        </stackView>
+                                        <progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progressViewStyle="bar" translatesAutoresizingMaskIntoConstraints="NO" id="IcU-Lc-kf0">
+                                            <rect key="frame" x="0.0" y="38.5" width="157" height="2.5"/>
+                                            <color key="backgroundColor" red="0.1461089551448822" green="0.16114577651023865" blue="0.17342603206634521" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                            <color key="progressTintColor" red="1" green="0.53333333329999999" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
+                                        </progressView>
+                                    </subviews>
+                                    <viewLayoutGuide key="safeArea" id="qEk-QE-Gm4"/>
+                                </stackView>
+                            </subviews>
+                            <connections>
+                                <outletCollection property="gestureRecognizers" destination="brR-fc-lZO" appends="YES" id="Nb4-rh-jQL"/>
+                                <outletCollection property="gestureRecognizers" destination="F5d-0u-KFK" appends="YES" id="vlA-dj-cvy"/>
+                                <outletCollection property="gestureRecognizers" destination="LWT-xp-2fu" appends="YES" id="ska-dZ-uCt"/>
+                            </connections>
+                        </stackView>
+                        <stackView opaque="NO" contentMode="scaleToFill" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="Lh6-Gu-frg" userLabel="Control Stack View">
+                            <rect key="frame" x="214" y="0.0" width="130" height="40"/>
+                            <subviews>
+                                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Hmp-0g-6lI" userLabel="Previous">
+                                    <rect key="frame" x="0.0" y="0.0" width="40" height="40"/>
+                                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                    <constraints>
+                                        <constraint firstAttribute="width" constant="40" id="Seu-Pw-atZ"/>
+                                        <constraint firstAttribute="height" constant="40" id="upi-oq-Tgr"/>
+                                        <constraint firstAttribute="width" secondItem="Hmp-0g-6lI" secondAttribute="height" multiplier="1:1" id="zAa-Io-XGm"/>
+                                    </constraints>
+                                    <state key="normal" image="MiniPrev"/>
+                                    <connections>
+                                        <action selector="handlePrevious:" destination="-1" eventType="touchUpInside" id="3MB-Hc-E2Q"/>
+                                    </connections>
+                                </button>
+                                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2Kp-xd-t2N" userLabel="Play">
+                                    <rect key="frame" x="45" y="0.0" width="40" height="40"/>
+                                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                    <state key="normal" image="MiniPause"/>
+                                    <connections>
+                                        <action selector="handlePlayPause:" destination="-1" eventType="touchUpInside" id="nOQ-xZ-48F"/>
+                                        <outletCollection property="gestureRecognizers" destination="RZE-7i-aax" appends="YES" id="rU5-pl-eJw"/>
+                                    </connections>
+                                </button>
+                                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eyt-Pj-hU6" userLabel="Next">
+                                    <rect key="frame" x="90" y="0.0" width="40" height="40"/>
+                                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                    <state key="normal" image="MiniNext"/>
+                                    <connections>
+                                        <action selector="handleNext:" destination="-1" eventType="touchUpInside" id="FDe-aX-DFt"/>
+                                    </connections>
+                                </button>
+                            </subviews>
+                            <constraints>
+                                <constraint firstItem="eyt-Pj-hU6" firstAttribute="height" secondItem="Hmp-0g-6lI" secondAttribute="height" id="4jQ-mM-QRc"/>
+                                <constraint firstItem="2Kp-xd-t2N" firstAttribute="height" secondItem="Hmp-0g-6lI" secondAttribute="height" id="Gc1-PX-mRK"/>
+                                <constraint firstItem="eyt-Pj-hU6" firstAttribute="width" secondItem="Hmp-0g-6lI" secondAttribute="width" id="p1p-oG-OhJ"/>
+                                <constraint firstItem="2Kp-xd-t2N" firstAttribute="width" secondItem="Hmp-0g-6lI" secondAttribute="width" id="wqC-bA-N0c"/>
+                            </constraints>
+                        </stackView>
+                    </subviews>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="40" id="uhh-wt-a89"/>
+                    </constraints>
+                </stackView>
+            </subviews>
+            <color key="backgroundColor" red="0.13333333333333333" green="0.15686274509803921" blue="0.17254901960784313" alpha="1" colorSpace="calibratedRGB"/>
+            <gestureRecognizers/>
+            <constraints>
+                <constraint firstItem="ciB-dn-lxu" firstAttribute="leading" secondItem="3Tx-iI-Z1w" secondAttribute="leading" constant="8" id="Wlf-Uy-z8K"/>
+                <constraint firstItem="3Tx-iI-Z1w" firstAttribute="bottom" secondItem="ciB-dn-lxu" secondAttribute="bottom" constant="8" id="fLR-CQ-9Es"/>
+                <constraint firstItem="3Tx-iI-Z1w" firstAttribute="trailing" secondItem="ciB-dn-lxu" secondAttribute="trailing" constant="8" id="gWp-eU-MSF"/>
+                <constraint firstItem="ciB-dn-lxu" firstAttribute="top" secondItem="3Tx-iI-Z1w" secondAttribute="top" constant="8" id="rGr-wd-DPi"/>
+            </constraints>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <viewLayoutGuide key="safeArea" id="3Tx-iI-Z1w"/>
+            <point key="canvasLocation" x="204.80000000000001" y="293.25337331334333"/>
+        </view>
+        <swipeGestureRecognizer direction="right" id="F5d-0u-KFK" userLabel="rightSwipeRecognizer">
+            <connections>
+                <action selector="handleSwipe:" destination="-1" id="ey7-0c-s91"/>
+            </connections>
+        </swipeGestureRecognizer>
+        <swipeGestureRecognizer direction="left" id="LWT-xp-2fu" userLabel="leftSwipeRecognizer">
+            <connections>
+                <action selector="handleSwipe:" destination="-1" id="yyG-mh-caS"/>
+            </connections>
+        </swipeGestureRecognizer>
+        <pongPressGestureRecognizer allowableMovement="10" minimumPressDuration="0.5" id="RZE-7i-aax">
+            <connections>
+                <action selector="handleLongPressPlayPause:" destination="-1" id="e0w-jB-cB1"/>
+            </connections>
+        </pongPressGestureRecognizer>
+        <tapGestureRecognizer id="brR-fc-lZO" userLabel="handleFullScreen">
+            <connections>
+                <action selector="handleFullScreen:" destination="-1" id="ovS-Zp-zdC"/>
+            </connections>
+        </tapGestureRecognizer>
+    </objects>
+    <resources>
+        <image name="MiniNext" width="24" height="24"/>
+        <image name="MiniPause" width="24" height="24"/>
+        <image name="MiniPrev" width="24" height="24"/>
+        <image name="vlc-xmas" width="20" height="20"/>
+    </resources>
+</document>

+ 2 - 0
Resources/en.lproj/Localizable.strings

@@ -181,6 +181,8 @@
 "BWD_BUTTON" = "Jump Backwards";
 "FWD_BUTTON" = "Jump Forwards";
 "PLAY_BUTTON" = "Play";
+"NEXT_BUTTON" = "Next";
+"PREV_BUTTON" = "Previous";
 "PLAY_ALL_BUTTON" = "Play all";
 
 "VERSION_FORMAT" = "Version: %@";

+ 171 - 0
Sources/MiniPlayer/AudioMiniPlayer.swift

@@ -0,0 +1,171 @@
+/*****************************************************************************
+ * AudioMiniPlayer.swift
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2019 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Soomin Lee <bubu # mikan.io>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+@objc(VLCAudioMiniPlayer)
+class AudioMiniPlayer: UIView, MiniPlayer {
+    var visible: Bool = false
+    var contentHeight: Float {
+        return 72.0
+    }
+
+    @IBOutlet private weak var audioMiniPlayer: UIView!
+    @IBOutlet private weak var artworkImageView: UIImageView!
+    @IBOutlet private weak var titleLabel: UILabel!
+    @IBOutlet private weak var artistLabel: UILabel!
+    @IBOutlet private weak var progressBarView: UIProgressView!
+    @IBOutlet private weak var playPauseButton: UIButton!
+    @IBOutlet private weak var previousButton: UIButton!
+    @IBOutlet private weak var nextButton: UIButton!
+
+    private lazy var playbackController = VLCPlaybackController.sharedInstance()
+
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        initView()
+        setupConstraint()
+    }
+
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    func updatePlayPauseButton() {
+        let imageName = playbackController.isPlaying ? "MiniPause" : "MiniPlay"
+        playPauseButton.imageView?.image = UIImage(named: imageName)
+    }
+}
+
+// MARK: - Private initializers
+
+private extension AudioMiniPlayer {
+    private func initView() {
+        Bundle.main.loadNibNamed("AudioMiniPlayer", owner: self, options: nil)
+        addSubview(audioMiniPlayer)
+
+        audioMiniPlayer.clipsToBounds = true
+        audioMiniPlayer.layer.cornerRadius = 4
+
+        progressBarView.clipsToBounds = true
+        progressBarView.layer.cornerRadius = 1
+
+        artworkImageView.clipsToBounds = true
+        artworkImageView.layer.cornerRadius = 2
+
+        playPauseButton.accessibilityLabel = NSLocalizedString("PLAY_PAUSE_BUTTON", comment: "")
+        nextButton.accessibilityLabel = NSLocalizedString("NEXT_BUTTON", comment: "")
+        previousButton.accessibilityLabel = NSLocalizedString("PREV_BUTTON", comment: "")
+    }
+
+    private func setupConstraint() {
+        var guide: LayoutAnchorContainer = self
+
+        if #available(iOS 11.0, *) {
+            guide = safeAreaLayoutGuide
+        }
+        audioMiniPlayer.translatesAutoresizingMaskIntoConstraints = false
+        NSLayoutConstraint.activate([audioMiniPlayer.leadingAnchor.constraint(equalTo: guide.leadingAnchor,
+                                                                              constant: 8),
+                                     audioMiniPlayer.trailingAnchor.constraint(equalTo: guide.trailingAnchor,
+                                                                               constant: -8),
+                                     audioMiniPlayer.bottomAnchor.constraint(equalTo: bottomAnchor,
+                                                                             constant: -8),
+                                     ])
+    }
+}
+
+// MARK: - VLCPlaybackControllerDelegate
+
+extension AudioMiniPlayer {
+    func prepare(forMediaPlayback controller: VLCPlaybackController) {
+        updatePlayPauseButton()
+        controller.delegate = self
+        controller.recoverDisplayedMetadata()
+        // For now, AudioMiniPlayer will be used for all media
+        controller.videoOutputView = artworkImageView
+    }
+
+    func mediaPlayerStateChanged(_ currentState: VLCMediaPlayerState,
+                                 isPlaying: Bool,
+                                 currentMediaHasTrackToChooseFrom: Bool,
+                                 currentMediaHasChapters: Bool,
+                                 for controller: VLCPlaybackController) {
+        updatePlayPauseButton()
+    }
+
+    func displayMetadata(for controller: VLCPlaybackController, metadata: VLCMetaData) {
+        setMediaInfo(metadata)
+    }
+
+    func playbackPositionUpdated(_ controller: VLCPlaybackController) {
+        progressBarView.progress = controller.playbackPosition
+    }
+}
+
+// MARK: - UI Receivers
+
+private extension AudioMiniPlayer {
+    @IBAction private func handlePrevious(_ sender: UIButton) {
+        playbackController.previous()
+    }
+
+    @IBAction private func handlePlayPause(_ sender: UIButton) {
+        playbackController.playPause()
+    }
+
+    @IBAction private func handleNext(_ sender: UIButton) {
+        playbackController.next()
+    }
+
+    @IBAction private func handleFullScreen(_ sender: Any) {
+        UIApplication.shared.sendAction(#selector(VLCPlayerDisplayController.showFullscreenPlayback),
+                                        to: nil,
+                                        from: self,
+                                        for: nil)
+    }
+
+    @IBAction private func handleSwipe(_ sender: UISwipeGestureRecognizer) {
+        switch sender.direction {
+        case .right:
+            playbackController.previous()
+        case .left:
+            playbackController.next()
+        default:
+            break
+        }
+    }
+
+    @IBAction private func handleLongPressPlayPause(_ sender: UILongPressGestureRecognizer) {
+        switch sender.state {
+        // case .began:
+        // In the case of .began we could a an icon like the old miniplayer
+        case .ended:
+            playbackController.stopPlayback()
+        case .cancelled, .failed:
+            playbackController.playPause()
+            updatePlayPauseButton()
+        default:
+            break
+        }
+    }
+}
+
+// MARK: - Setters
+
+private extension AudioMiniPlayer {
+    private func setMediaInfo(_ metadata: VLCMetaData) {
+        titleLabel.text = metadata.title
+        artistLabel.text = metadata.artist
+        if metadata.isAudioOnly {
+            artworkImageView.image = metadata.artworkImage ?? UIImage(named: "no-artwork")
+        }
+    }
+}

+ 17 - 0
Sources/MiniPlayer/MiniPlayer.swift

@@ -0,0 +1,17 @@
+/*****************************************************************************
+ * MiniPlayer.swift
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2019 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Soomin Lee <bubu # mikan.io>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+@objc(VLCMiniPlayer)
+protocol MiniPlayer: VLCMiniPlaybackViewInterface, VLCPlaybackControllerDelegate {
+    var contentHeight: Float { get }
+    func updatePlayPauseButton()
+}

+ 0 - 21
Sources/VLCMiniPlaybackView.h

@@ -1,21 +0,0 @@
-/*****************************************************************************
- * VLCMiniPlaybackView.h
- * VLC for iOS
- *****************************************************************************
- * Copyright (c) 2015 VideoLAN. All rights reserved.
- * $Id$
- *
- * Author: Felix Paul Kühne <fkuehne # videolan.org>
- *
- * Refer to the COPYING file of the official project for license.
- *****************************************************************************/
-
-#import "VLCPlaybackController.h"
-#import "VLCPlayerDisplayController.h"
-#import "VLCFrostedGlasView.h"
-
-@class VLCPlaybackController;
-@interface VLCMiniPlaybackView : VLCFrostedGlasView <VLCPlaybackControllerDelegate, VLCMiniPlaybackViewInterface>
-// just a state keeper for animation, has no other implementation
-@property (nonatomic) BOOL visible;
-@end

+ 0 - 234
Sources/VLCMiniPlaybackView.m

@@ -1,234 +0,0 @@
-/*****************************************************************************
- * VLCMiniPlaybackView.m
- * VLC for iOS
- *****************************************************************************
- * Copyright (c) 2015 VideoLAN. All rights reserved.
- * $Id$
- *
- * Author: Felix Paul Kühne <fkuehne # videolan.org>
- *         Carola Nitz <caro # videolan.org>
- *
- * Refer to the COPYING file of the official project for license.
- *****************************************************************************/
-
-#import "VLCMiniPlaybackView.h"
-#import "VLCMetadata.h"
-#import "VLC-Swift.h"
-
-@interface VLCMiniPlaybackView () <UIGestureRecognizerDelegate>
-{
-    UIImageView *_artworkView;
-    UIView *_videoView;
-    UIButton *_previousButton;
-    UIButton *_playPauseButton;
-    UIButton *_nextButton;
-    UIButton *_expandButton;
-    UILabel *_metaDataLabel;
-    UITapGestureRecognizer *_tapRecognizer;
-    UIStackView *_stackView;
-}
-
-@end
-
-@implementation VLCMiniPlaybackView
-
-- (instancetype)initWithFrame:(CGRect)viewFrame
-{
-    self = [super initWithFrame:viewFrame];
-    if (self) {
-        [self setupSubviews];
-    }
-    return self;
-}
-
-- (void)setupSubviews
-{
-    CGFloat buttonSize = 44.;
-    CGFloat videoSize = 60.;
-    CGFloat padding = 10.;
-
-    _artworkView = [[UIImageView alloc] initWithFrame:CGRectZero];
-    _artworkView.translatesAutoresizingMaskIntoConstraints = NO;
-    _artworkView.clipsToBounds = YES;
-    _artworkView.backgroundColor = [UIColor VLCDarkBackgroundColor];
-    _artworkView.opaque = YES;
-    [self addSubview:_artworkView];
-
-    _videoView = [[UIView alloc] initWithFrame:CGRectZero];
-    [_videoView setClipsToBounds:YES];
-    _videoView.userInteractionEnabled = NO;
-    _videoView.translatesAutoresizingMaskIntoConstraints = NO;
-    [self addSubview:_videoView];
-
-    _expandButton = [UIButton buttonWithType:UIButtonTypeCustom];
-    [_expandButton setImage:[UIImage imageNamed:@"ratioIcon"] forState:UIControlStateNormal];
-    _expandButton.translatesAutoresizingMaskIntoConstraints = NO;
-    [_expandButton addTarget:self action:@selector(pushFullPlaybackView:) forControlEvents:UIControlEventTouchUpInside];
-    _expandButton.accessibilityLabel = NSLocalizedString(@"FULLSCREEN_PLAYBACK", nil);
-
-    _nextButton = [UIButton buttonWithType:UIButtonTypeCustom];
-    [_nextButton setImage:[UIImage imageNamed:@"forwardIcon"] forState:UIControlStateNormal];
-    _nextButton.translatesAutoresizingMaskIntoConstraints = NO;
-    [_nextButton addTarget:self action:@selector(nextAction:) forControlEvents:UIControlEventTouchUpInside];
-    _nextButton.accessibilityLabel = NSLocalizedString(@"FWD_BUTTON", nil);
-
-    _playPauseButton = [UIButton buttonWithType:UIButtonTypeCustom];
-    [_playPauseButton setImage:[UIImage imageNamed:@"playIcon"] forState:UIControlStateNormal];
-    _playPauseButton.translatesAutoresizingMaskIntoConstraints = NO;
-    [_playPauseButton addTarget:self action:@selector(playPauseAction:) forControlEvents:UIControlEventTouchUpInside];
-    _playPauseButton.accessibilityLabel = NSLocalizedString(@"PLAY_PAUSE_BUTTON", nil);
-    _playPauseButton.accessibilityHint = NSLocalizedString(@"LONGPRESS_TO_STOP", nil);
-    UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(playPauseLongPress:)];
-    [_playPauseButton addGestureRecognizer:longPressRecognizer];
-
-    _previousButton = [UIButton buttonWithType:UIButtonTypeCustom];
-    [_previousButton setImage:[UIImage imageNamed:@"backIcon"] forState:UIControlStateNormal];
-    [_previousButton sizeToFit];
-    _previousButton.translatesAutoresizingMaskIntoConstraints = NO;
-    [_previousButton addTarget:self action:@selector(previousAction:) forControlEvents:UIControlEventTouchUpInside];
-    _previousButton.accessibilityLabel = NSLocalizedString(@"BWD_BUTTON", nil);
-
-    _metaDataLabel = [[UILabel alloc] initWithFrame:CGRectZero];
-    _metaDataLabel.font = [UIFont systemFontOfSize:12.];
-    _metaDataLabel.textColor = [UIColor VLCLightTextColor];
-    _metaDataLabel.numberOfLines = 0;
-    _metaDataLabel.translatesAutoresizingMaskIntoConstraints = NO;
-    [self addSubview:_metaDataLabel];
-
-    _stackView = [[UIStackView alloc] initWithArrangedSubviews:@[_previousButton, _playPauseButton, _nextButton, _expandButton]];
-    _stackView.translatesAutoresizingMaskIntoConstraints = NO;
-    _stackView.distribution = UIStackViewDistributionFillEqually;
-    [self addSubview:_stackView];
-
-    id<VLCLayoutAnchorContainer> guide = self;
-    if (@available(iOS 11.0, *)) {
-        guide = self.safeAreaLayoutGuide;
-    }
-
-    [NSLayoutConstraint activateConstraints:@[
-                                              [_artworkView.leftAnchor constraintEqualToAnchor:self.leftAnchor],
-                                              [_artworkView.topAnchor constraintEqualToAnchor:self.topAnchor],
-                                              [_artworkView.rightAnchor constraintEqualToAnchor:_metaDataLabel.leftAnchor constant:-padding],
-                                              [_artworkView.bottomAnchor constraintEqualToAnchor:guide.bottomAnchor],
-                                              [_artworkView.widthAnchor constraintEqualToConstant:videoSize],
-                                              [_artworkView.heightAnchor constraintEqualToAnchor:_artworkView.widthAnchor],
-
-                                              [_videoView.leftAnchor constraintEqualToAnchor:self.leftAnchor],
-                                              [_videoView.topAnchor constraintEqualToAnchor:self.topAnchor],
-                                              [_videoView.rightAnchor constraintEqualToAnchor:_metaDataLabel.leftAnchor constant:-padding],
-                                              [_videoView.bottomAnchor constraintEqualToAnchor:guide.bottomAnchor],
-                                              [_videoView.widthAnchor constraintEqualToConstant:videoSize],
-                                              [_videoView.heightAnchor constraintEqualToAnchor:_videoView.widthAnchor],
-
-                                              [_metaDataLabel.topAnchor constraintEqualToAnchor:self.topAnchor],
-                                              [_metaDataLabel.rightAnchor constraintLessThanOrEqualToAnchor:_stackView.leftAnchor constant:- padding],
-                                              [_metaDataLabel.bottomAnchor constraintEqualToAnchor:guide.bottomAnchor],
-                                              [_previousButton.widthAnchor constraintEqualToConstant:buttonSize],
-
-                                              [_stackView.topAnchor constraintEqualToAnchor:self.topAnchor],
-                                              [_stackView.rightAnchor constraintEqualToAnchor:self.rightAnchor],
-                                              [_stackView.bottomAnchor constraintEqualToAnchor:guide.bottomAnchor],
-                                              ]];
-
-    _tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapRecognized)];
-    _tapRecognizer.delegate = self;
-    [self addGestureRecognizer:_tapRecognizer];
-
-#if TARGET_OS_IOS
-    _tapRecognizer.numberOfTouchesRequired = 1;
-#endif
-}
-
-- (void)tapRecognized
-{
-    [self pushFullPlaybackView:nil];
-}
-
-- (void)previousAction:(id)sender
-{
-    [[VLCPlaybackController sharedInstance] previous];
-}
-
-- (void)playPauseAction:(id)sender
-{
-    [[VLCPlaybackController sharedInstance] playPause];
-}
-
-- (void)playPauseLongPress:(UILongPressGestureRecognizer *)recognizer
-{
-    switch (recognizer.state) {
-        case UIGestureRecognizerStateBegan:
-            [_playPauseButton setImage:[UIImage imageNamed:@"stopIcon"] forState:UIControlStateNormal];
-            break;
-        case UIGestureRecognizerStateEnded:
-            [[VLCPlaybackController sharedInstance] stopPlayback];
-            break;
-        case UIGestureRecognizerStateCancelled:
-        case UIGestureRecognizerStateFailed:
-            [self updatePlayPauseButton];
-            break;
-        default:
-            break;
-    }
-}
-
-- (void)nextAction:(id)sender
-{
-    [[VLCPlaybackController sharedInstance] next];
-}
-
-- (void)pushFullPlaybackView:(id)sender
-{
-    [[UIApplication sharedApplication] sendAction:@selector(showFullscreenPlayback) to:nil from:self forEvent:nil];
-}
-
-- (void)updatePlayPauseButton
-{
-    const BOOL isPlaying = [VLCPlaybackController sharedInstance].isPlaying;
-    UIImage *playPauseImage = isPlaying ? [UIImage imageNamed:@"pauseIcon"] : [UIImage imageNamed:@"playIcon"];
-    [_playPauseButton setImage:playPauseImage forState:UIControlStateNormal];
-}
-
-- (void)prepareForMediaPlayback:(VLCPlaybackController *)controller
-{
-    [self updatePlayPauseButton];
-    controller.delegate = self;
-    [controller recoverDisplayedMetadata];
-    _videoView.hidden = false;
-    controller.videoOutputView = _videoView;
-}
-
-- (void)mediaPlayerStateChanged:(VLCMediaPlayerState)currentState
-                      isPlaying:(BOOL)isPlaying
-currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
-        currentMediaHasChapters:(BOOL)currentMediaHasChapters
-          forPlaybackController:(VLCPlaybackController *)controller
-{
-    [self updatePlayPauseButton];
-}
-
-- (void)displayMetadataForPlaybackController:(VLCPlaybackController *)controller metadata:(VLCMetaData *)metadata
-{
-    if (metadata.isAudioOnly) {
-        _artworkView.contentMode = UIViewContentModeScaleAspectFill;
-        _artworkView.image = metadata.artworkImage?: [UIImage imageNamed:@"no-artwork"];
-        _videoView.hidden = YES;
-    } else {
-        _artworkView.image = nil;
-        _videoView.hidden = NO;
-    }
-
-    NSString *metaDataString;
-    if (metadata.artist)
-        metaDataString = metadata.artist;
-    if (metadata.albumName)
-        metaDataString = [metaDataString stringByAppendingFormat:@" — %@", metadata.albumName];
-    if (metaDataString)
-        metaDataString = [metaDataString stringByAppendingFormat:@"\n%@", metadata.title];
-    else
-        metaDataString = metadata.title;
-
-    _metaDataLabel.text = metaDataString;
-}
-
-@end

+ 6 - 6
Sources/VLCPlayerDisplayController.m

@@ -12,7 +12,6 @@
 
 #import "VLCPlayerDisplayController.h"
 #import "VLCPlaybackController.h"
-#import "VLCMiniPlaybackView.h"
 #import "VLCPlaybackNavigationController.h"
 #import "VLCPlaybackController+MediaLibrary.h"
 #import "VLC-Swift.h"
@@ -40,7 +39,7 @@ static NSString *const VLCPlayerDisplayControllerDisplayModeKey = @"VLCPlayerDis
 
 @interface VLCPlayerDisplayController () <VLCMovieViewControllerDelegate>
 @property (nonatomic, strong) UIViewController<VLCPlaybackControllerDelegate> *movieViewController;
-@property (nonatomic, strong) UIView<VLCPlaybackControllerDelegate, VLCMiniPlaybackViewInterface> *miniPlaybackView;
+@property (nonatomic, strong) UIView<VLCPlaybackControllerDelegate, VLCMiniPlayer> *miniPlaybackView;
 @property (nonatomic, strong) NSLayoutConstraint *bottomConstraint;
 @property (nonatomic, strong) VLCService *services;
 @end
@@ -266,7 +265,7 @@ static NSString *const VLCPlayerDisplayControllerDisplayModeKey = @"VLCPlayerDis
     }
 
     VLCPlaybackController *playbackController = [VLCPlaybackController sharedInstance];
-    UIView<VLCPlaybackControllerDelegate, VLCMiniPlaybackViewInterface> *miniPlaybackView = self.miniPlaybackView;
+    UIView<VLCPlaybackControllerDelegate, VLCMiniPlayer> *miniPlaybackView = self.miniPlaybackView;
     const NSTimeInterval animationDuration = 0.25;
     const BOOL activePlaybackSession = playbackController.isPlaying || playbackController.willPlay;
     const BOOL miniPlayerVisible = miniPlaybackView.visible;
@@ -282,14 +281,15 @@ static NSString *const VLCPlayerDisplayControllerDisplayModeKey = @"VLCPlayerDis
     void (^completionBlock)(BOOL) = nil;
     if (needsShow) {
         if (!miniPlaybackView) {
-            self.miniPlaybackView = miniPlaybackView = [[VLCMiniPlaybackView alloc] initWithFrame:CGRectZero];
+            // Until VideoMiniPlayer is integrated, only AudioMiniPlayer is used.
+            self.miniPlaybackView = miniPlaybackView = [[VLCAudioMiniPlayer alloc] initWithFrame:CGRectZero];
             miniPlaybackView.translatesAutoresizingMaskIntoConstraints = NO;
             miniPlaybackView.userInteractionEnabled = YES;
             [self.view addSubview:miniPlaybackView];
             _bottomConstraint = [miniPlaybackView.topAnchor constraintEqualToAnchor:self.view.bottomAnchor];
             [NSLayoutConstraint activateConstraints:
              @[_bottomConstraint,
-               [miniPlaybackView.heightAnchor constraintEqualToConstant:60.0],
+               [miniPlaybackView.heightAnchor constraintEqualToConstant:self.miniPlaybackView.contentHeight],
                [miniPlaybackView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor],
                [miniPlaybackView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor],
                ]];
@@ -299,7 +299,7 @@ static NSString *const VLCPlayerDisplayControllerDisplayModeKey = @"VLCPlayerDis
     } else if (needsHide) {
         miniPlaybackView.visible = NO;
         completionBlock = ^(BOOL finished) {
-            UIView<VLCPlaybackControllerDelegate, VLCMiniPlaybackViewInterface> *miniPlaybackView = self.miniPlaybackView;
+            UIView<VLCPlaybackControllerDelegate, VLCMiniPlayer> *miniPlaybackView = self.miniPlaybackView;
             if (miniPlaybackView.visible == NO) {
                 [miniPlaybackView removeFromSuperview];
                 self.miniPlaybackView = nil;

+ 30 - 6
VLC.xcodeproj/project.pbxproj

@@ -191,7 +191,6 @@
 		7D94FCDF16DE7D1000F2623B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D94FCDE16DE7D1000F2623B /* UIKit.framework */; };
 		7D94FCE116DE7D1000F2623B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D94FCE016DE7D1000F2623B /* Foundation.framework */; };
 		7D94FCE316DE7D1000F2623B /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D94FCE216DE7D1000F2623B /* CoreGraphics.framework */; };
-		7D95610B1AF3E9E800779745 /* VLCMiniPlaybackView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D95610A1AF3E9E800779745 /* VLCMiniPlaybackView.m */; };
 		7D9870641A3E03D5009CF27D /* papasscode_background.png in Resources */ = {isa = PBXBuildFile; fileRef = 7D98705E1A3E03D5009CF27D /* papasscode_background.png */; };
 		7D9870651A3E03D5009CF27D /* papasscode_background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 7D98705F1A3E03D5009CF27D /* papasscode_background@2x.png */; };
 		7D9870661A3E03D5009CF27D /* papasscode_failed_bg.png in Resources */ = {isa = PBXBuildFile; fileRef = 7D9870601A3E03D5009CF27D /* papasscode_failed_bg.png */; };
@@ -251,11 +250,14 @@
 		7DF90B4B1BE7A8110059C0E3 /* IASKSpecifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF90B491BE7A8110059C0E3 /* IASKSpecifier.m */; };
 		7DF9352F1958AB0600E60FD4 /* UIColor+Presets.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DF9352E1958AB0600E60FD4 /* UIColor+Presets.m */; };
 		81334053F6D89AB90E14A1C3 /* libPods-VLC-iOSTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 91CCB170FBC97B6B93B99E0A /* libPods-VLC-iOSTests.a */; };
+		8D144D6322298E8E00984C46 /* AudioMiniPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D144D6222298E8E00984C46 /* AudioMiniPlayer.swift */; };
 		8D222DC220F779F1009C0D34 /* MediaEditCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D222DC120F779F1009C0D34 /* MediaEditCell.swift */; };
+		8D3B4C0E2226E49A00B9F652 /* AudioMiniPlayer.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8D3B4C0D2226E49A00B9F652 /* AudioMiniPlayer.xib */; };
 		8D43712D2056AF1600F36458 /* VLCRendererDiscovererManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D43712C2056AF1600F36458 /* VLCRendererDiscovererManager.swift */; };
 		8D437154205808FF00F36458 /* VLCActionSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D437153205808FF00F36458 /* VLCActionSheet.swift */; };
 		8D4F9B472141630000E478BE /* MediaModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4F9B462141630000E478BE /* MediaModel.swift */; };
 		8D66A47320AC61B900FA5B92 /* MediaLibraryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D66A47220AC61B900FA5B92 /* MediaLibraryService.swift */; };
+		8D6E1588223BBAF600077DD3 /* MiniPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D6E1587223BBAF600077DD3 /* MiniPlayer.swift */; };
 		8DD6516F208C89BC0052EE68 /* VLCAccessibilityIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD6516E208C89BC0052EE68 /* VLCAccessibilityIdentifier.swift */; };
 		8DD651BA208F6AF00052EE68 /* VLCActionSheetCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD651B9208F6AF00052EE68 /* VLCActionSheetCell.swift */; };
 		8DD651C4208F786F0052EE68 /* VLCActionSheetSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD651C3208F786F0052EE68 /* VLCActionSheetSectionHeader.swift */; };
@@ -735,8 +737,6 @@
 		7D94FCDE16DE7D1000F2623B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
 		7D94FCE016DE7D1000F2623B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
 		7D94FCE216DE7D1000F2623B /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
-		7D9561091AF3E9E800779745 /* VLCMiniPlaybackView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCMiniPlaybackView.h; path = Sources/VLCMiniPlaybackView.h; sourceTree = SOURCE_ROOT; };
-		7D95610A1AF3E9E800779745 /* VLCMiniPlaybackView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCMiniPlaybackView.m; path = Sources/VLCMiniPlaybackView.m; sourceTree = SOURCE_ROOT; };
 		7D98705E1A3E03D5009CF27D /* papasscode_background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = papasscode_background.png; sourceTree = "<group>"; };
 		7D98705F1A3E03D5009CF27D /* papasscode_background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "papasscode_background@2x.png"; sourceTree = "<group>"; };
 		7D9870601A3E03D5009CF27D /* papasscode_failed_bg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = papasscode_failed_bg.png; sourceTree = "<group>"; };
@@ -824,11 +824,14 @@
 		7DF9352D1958AB0600E60FD4 /* UIColor+Presets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIColor+Presets.h"; path = "Sources/UIColor+Presets.h"; sourceTree = SOURCE_ROOT; };
 		7DF9352E1958AB0600E60FD4 /* UIColor+Presets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIColor+Presets.m"; path = "Sources/UIColor+Presets.m"; sourceTree = SOURCE_ROOT; };
 		7FC9CCF39DD8843873A42D34 /* Pods-VLC-iOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VLC-iOSTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-VLC-iOSTests/Pods-VLC-iOSTests.release.xcconfig"; sourceTree = "<group>"; };
+		8D144D6222298E8E00984C46 /* AudioMiniPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioMiniPlayer.swift; sourceTree = "<group>"; };
 		8D222DC120F779F1009C0D34 /* MediaEditCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MediaEditCell.swift; path = Sources/MediaEditCell.swift; sourceTree = "<group>"; };
+		8D3B4C0D2226E49A00B9F652 /* AudioMiniPlayer.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AudioMiniPlayer.xib; sourceTree = "<group>"; };
 		8D43712C2056AF1600F36458 /* VLCRendererDiscovererManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = VLCRendererDiscovererManager.swift; path = Sources/VLCRendererDiscovererManager.swift; sourceTree = "<group>"; };
 		8D437153205808FF00F36458 /* VLCActionSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VLCActionSheet.swift; sourceTree = "<group>"; };
 		8D4F9B462141630000E478BE /* MediaModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaModel.swift; sourceTree = "<group>"; };
 		8D66A47220AC61B900FA5B92 /* MediaLibraryService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaLibraryService.swift; sourceTree = "<group>"; };
+		8D6E1587223BBAF600077DD3 /* MiniPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MiniPlayer.swift; sourceTree = "<group>"; };
 		8DD6516E208C89BC0052EE68 /* VLCAccessibilityIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VLCAccessibilityIdentifier.swift; sourceTree = "<group>"; };
 		8DD651B9208F6AF00052EE68 /* VLCActionSheetCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VLCActionSheetCell.swift; sourceTree = "<group>"; };
 		8DD651C3208F786F0052EE68 /* VLCActionSheetSectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VLCActionSheetSectionHeader.swift; sourceTree = "<group>"; };
@@ -1395,6 +1398,7 @@
 		7D5F7AB9175265B2006CCCFA /* Playback */ = {
 			isa = PBXGroup;
 			children = (
+				8D144D6122298E5800984C46 /* MiniPlayer */,
 				416443852048419E00CAC646 /* DeviceMotion.swift */,
 				DD8F842F1B00EB3B0009138A /* VLCPlaybackController+MediaLibrary.h */,
 				DD8F84301B00EB3B0009138A /* VLCPlaybackController+MediaLibrary.m */,
@@ -1588,6 +1592,7 @@
 		7DADC55C1704FAA8001DAC63 /* XIBs */ = {
 			isa = PBXGroup;
 			children = (
+				8D3B4C0C2226E47900B9F652 /* MiniPlayer */,
 				41D7DD2020C1FC2D00AD94F6 /* VLCLabelCell.xib */,
 				41273A3B1A955C4100A2EF77 /* VLCMigrationViewController.xib */,
 				7DC19AF41868CDB800810BF7 /* First Steps */,
@@ -1702,8 +1707,6 @@
 		7DEC8BE01BD686D3006E1093 /* Playback */ = {
 			isa = PBXGroup;
 			children = (
-				7D9561091AF3E9E800779745 /* VLCMiniPlaybackView.h */,
-				7D95610A1AF3E9E800779745 /* VLCMiniPlaybackView.m */,
 				7DE56C181AD93F9100E8CA00 /* VLCPlaybackController.h */,
 				7DE56C191AD93F9100E8CA00 /* VLCPlaybackController.m */,
 				DD510B6E1B14E564003BA71C /* VLCPlayerDisplayController.h */,
@@ -1875,6 +1878,25 @@
 			name = Dropbox;
 			sourceTree = "<group>";
 		};
+		8D144D6122298E5800984C46 /* MiniPlayer */ = {
+			isa = PBXGroup;
+			children = (
+				8D144D6222298E8E00984C46 /* AudioMiniPlayer.swift */,
+				8D6E1587223BBAF600077DD3 /* MiniPlayer.swift */,
+			);
+			name = MiniPlayer;
+			path = Sources/MiniPlayer;
+			sourceTree = "<group>";
+		};
+		8D3B4C0C2226E47900B9F652 /* MiniPlayer */ = {
+			isa = PBXGroup;
+			children = (
+				8D3B4C0D2226E49A00B9F652 /* AudioMiniPlayer.xib */,
+			);
+			name = MiniPlayer;
+			path = Resources/Xib/MiniPlayer;
+			sourceTree = "<group>";
+		};
 		8DD651B0208F62B70052EE68 /* VLCActionSheet */ = {
 			isa = PBXGroup;
 			children = (
@@ -2521,6 +2543,7 @@
 				7D9870681A3E03D5009CF27D /* papasscode_marker.png in Resources */,
 				7D32B384185E293D006CA474 /* Raleway.woff in Resources */,
 				7D9870691A3E03D5009CF27D /* papasscode_marker@2x.png in Resources */,
+				8D3B4C0E2226E49A00B9F652 /* AudioMiniPlayer.xib in Resources */,
 				7D5DD5C717590ABF001421E3 /* About Contents.html in Resources */,
 				7DBBF19B183AB4300009A339 /* VLCCloudStorageTableViewCell~iphone.xib in Resources */,
 				7D92897B1877467E009108FD /* VLCFirstStepsFourthPageViewController~iphone.xib in Resources */,
@@ -2894,11 +2917,11 @@
 				416443862048419E00CAC646 /* DeviceMotion.swift in Sources */,
 				7D9289751877459B009108FD /* VLCFirstStepsThirdPageViewController.m in Sources */,
 				41364DF621FF5B7D00AC22B3 /* ArtistCollectionViewCell.swift in Sources */,
-				7D95610B1AF3E9E800779745 /* VLCMiniPlaybackView.m in Sources */,
 				DD3EFF451BDEBCE500B68579 /* VLCLocalNetworkServiceBrowserManualConnect.m in Sources */,
 				8DF966B121188BDB00D0FCD6 /* VLCEditController.swift in Sources */,
 				7DC19B051868D1C400810BF7 /* VLCFirstStepsFifthPageViewController.m in Sources */,
 				DD3EFF311BDEBCE500B68579 /* VLCNetworkServerBrowserFTP.m in Sources */,
+				8D144D6322298E8E00984C46 /* AudioMiniPlayer.swift in Sources */,
 				8D4F9B472141630000E478BE /* MediaModel.swift in Sources */,
 				8DF966EF211C643D00D0FCD6 /* PlaylistModel.swift in Sources */,
 				9BADAF45185FBD9D00108BD8 /* VLCFrostedGlasView.m in Sources */,
@@ -3021,6 +3044,7 @@
 				7D1052E91A4DCC1100295F08 /* VLCOneDriveTableViewController.m in Sources */,
 				DD3EFF591BDEBCE500B68579 /* VLCLocalNetworkServiceUPnP.m in Sources */,
 				7D30F3D7183AB2F100FFC021 /* VLCNetworkListCell.m in Sources */,
+				8D6E1588223BBAF600077DD3 /* MiniPlayer.swift in Sources */,
 				7D1052EE1A4DCD1E00295F08 /* VLCOneDriveController.m in Sources */,
 				414396C22023316C005E3FAF /* AppearanceManager.swift in Sources */,
 				7D30F3DC183AB2F900FFC021 /* VLCNetworkLoginViewController.m in Sources */,

+ 6 - 0
vlc-ios/Images.xcassets/Movie View/MiniPlayer/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

+ 23 - 0
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniNext.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "next@1x.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "next@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "next@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

binární
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniNext.imageset/next@1x.png


binární
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniNext.imageset/next@2x.png


binární
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniNext.imageset/next@3x.png


+ 23 - 0
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPause.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "pause@1x.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "pause@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "pause@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

binární
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPause.imageset/pause@1x.png


binární
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPause.imageset/pause@2x.png


binární
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPause.imageset/pause@3x.png


+ 23 - 0
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPlay.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "play@1x.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "play@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "play@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

binární
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPlay.imageset/play@1x.png


binární
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPlay.imageset/play@2x.png


binární
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPlay.imageset/play@3x.png


+ 23 - 0
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPrev.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "prev@1x.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "prev@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "prev@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

binární
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPrev.imageset/prev@1x.png


binární
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPrev.imageset/prev@2x.png


binární
vlc-ios/Images.xcassets/Movie View/MiniPlayer/MiniPrev.imageset/prev@3x.png


+ 2 - 0
vlc-ios/VLC-iOS-Bridging-Header.h

@@ -29,3 +29,5 @@
 #import "VLCMediaFileDiscoverer.h"
 #import "VLCMigrationViewController.h"
 #import "VLCCloudStorageTableViewController.h"
+#import "VLCMetadata.h"
+#import "VLCPlayerDisplayController.h"