AudioMiniPlayer.swift 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*****************************************************************************
  2. * AudioMiniPlayer.swift
  3. * VLC for iOS
  4. *****************************************************************************
  5. * Copyright (c) 2019 VideoLAN. All rights reserved.
  6. * $Id$
  7. *
  8. * Authors: Soomin Lee <bubu # mikan.io>
  9. *
  10. * Refer to the COPYING file of the official project for license.
  11. *****************************************************************************/
  12. @objc(VLCAudioMiniPlayer)
  13. class AudioMiniPlayer: UIView, MiniPlayer {
  14. var visible: Bool = false
  15. var contentHeight: Float {
  16. return 72.0
  17. }
  18. @IBOutlet private weak var audioMiniPlayer: UIView!
  19. @IBOutlet private weak var artworkImageView: UIImageView!
  20. @IBOutlet private weak var titleLabel: UILabel!
  21. @IBOutlet private weak var artistLabel: UILabel!
  22. @IBOutlet private weak var progressBarView: UIProgressView!
  23. @IBOutlet private weak var playPauseButton: UIButton!
  24. @IBOutlet private weak var previousButton: UIButton!
  25. @IBOutlet private weak var nextButton: UIButton!
  26. private var mediaService: MediaLibraryService
  27. private lazy var playbackController = VLCPlaybackController.sharedInstance()
  28. @objc init(service: MediaLibraryService) {
  29. self.mediaService = service
  30. super.init(frame: .zero)
  31. initView()
  32. setupConstraint()
  33. }
  34. required init?(coder aDecoder: NSCoder) {
  35. fatalError("init(coder:) has not been implemented")
  36. }
  37. func updatePlayPauseButton() {
  38. let imageName = playbackController.isPlaying ? "MiniPause" : "MiniPlay"
  39. playPauseButton.imageView?.image = UIImage(named: imageName)
  40. }
  41. }
  42. // MARK: - Private initializers
  43. private extension AudioMiniPlayer {
  44. private func initView() {
  45. Bundle.main.loadNibNamed("AudioMiniPlayer", owner: self, options: nil)
  46. addSubview(audioMiniPlayer)
  47. audioMiniPlayer.clipsToBounds = true
  48. audioMiniPlayer.layer.cornerRadius = 4
  49. progressBarView.clipsToBounds = true
  50. progressBarView.layer.cornerRadius = 1
  51. artworkImageView.clipsToBounds = true
  52. artworkImageView.layer.cornerRadius = 2
  53. playPauseButton.accessibilityLabel = NSLocalizedString("PLAY_PAUSE_BUTTON", comment: "")
  54. nextButton.accessibilityLabel = NSLocalizedString("NEXT_BUTTON", comment: "")
  55. previousButton.accessibilityLabel = NSLocalizedString("PREV_BUTTON", comment: "")
  56. }
  57. private func setupConstraint() {
  58. var guide: LayoutAnchorContainer = self
  59. if #available(iOS 11.0, *) {
  60. guide = safeAreaLayoutGuide
  61. }
  62. audioMiniPlayer.translatesAutoresizingMaskIntoConstraints = false
  63. NSLayoutConstraint.activate([audioMiniPlayer.leadingAnchor.constraint(equalTo: guide.leadingAnchor,
  64. constant: 8),
  65. audioMiniPlayer.trailingAnchor.constraint(equalTo: guide.trailingAnchor,
  66. constant: -8),
  67. audioMiniPlayer.bottomAnchor.constraint(equalTo: bottomAnchor,
  68. constant: -8),
  69. ])
  70. }
  71. }
  72. // MARK: - VLCPlaybackControllerDelegate
  73. extension AudioMiniPlayer {
  74. func prepare(forMediaPlayback controller: VLCPlaybackController) {
  75. updatePlayPauseButton()
  76. controller.delegate = self
  77. controller.recoverDisplayedMetadata()
  78. // For now, AudioMiniPlayer will be used for all media
  79. controller.videoOutputView = artworkImageView
  80. }
  81. func mediaPlayerStateChanged(_ currentState: VLCMediaPlayerState,
  82. isPlaying: Bool,
  83. currentMediaHasTrackToChooseFrom: Bool,
  84. currentMediaHasChapters: Bool,
  85. for controller: VLCPlaybackController) {
  86. updatePlayPauseButton()
  87. }
  88. func displayMetadata(for controller: VLCPlaybackController, metadata: VLCMetaData) {
  89. setMediaInfo(metadata)
  90. }
  91. func playbackPositionUpdated(_ controller: VLCPlaybackController) {
  92. progressBarView.progress = controller.playbackPosition
  93. }
  94. func savePlaybackState(_ controller: VLCPlaybackController) {
  95. mediaService.savePlaybackState(from: controller)
  96. }
  97. func media(forPlaying media: VLCMedia) -> VLCMLMedia? {
  98. return mediaService.fetchMedia(with: media.url)
  99. }
  100. }
  101. // MARK: - UI Receivers
  102. private extension AudioMiniPlayer {
  103. @IBAction private func handlePrevious(_ sender: UIButton) {
  104. playbackController.previous()
  105. }
  106. @IBAction private func handlePlayPause(_ sender: UIButton) {
  107. playbackController.playPause()
  108. }
  109. @IBAction private func handleNext(_ sender: UIButton) {
  110. playbackController.next()
  111. }
  112. @IBAction private func handleFullScreen(_ sender: Any) {
  113. UIApplication.shared.sendAction(#selector(VLCPlayerDisplayController.showFullscreenPlayback),
  114. to: nil,
  115. from: self,
  116. for: nil)
  117. }
  118. @IBAction private func handleSwipe(_ sender: UISwipeGestureRecognizer) {
  119. switch sender.direction {
  120. case .right:
  121. playbackController.previous()
  122. case .left:
  123. playbackController.next()
  124. default:
  125. break
  126. }
  127. }
  128. @IBAction private func handleLongPressPlayPause(_ sender: UILongPressGestureRecognizer) {
  129. switch sender.state {
  130. // case .began:
  131. // In the case of .began we could a an icon like the old miniplayer
  132. case .ended:
  133. playbackController.stopPlayback()
  134. case .cancelled, .failed:
  135. playbackController.playPause()
  136. updatePlayPauseButton()
  137. default:
  138. break
  139. }
  140. }
  141. }
  142. // MARK: - Setters
  143. private extension AudioMiniPlayer {
  144. private func setMediaInfo(_ metadata: VLCMetaData) {
  145. titleLabel.text = metadata.title
  146. artistLabel.text = metadata.artist
  147. if metadata.isAudioOnly {
  148. artworkImageView.image = metadata.artworkImage ?? UIImage(named: "no-artwork")
  149. }
  150. }
  151. }