2 // PlayerViewController.swift
5 // Created by Pawel Dabrowski on 07/09/2018.
6 // Copyright © 2018 Fundacja Nowoczesna Polska. All rights reserved.
14 class PlayerViewController: WLViewController {
16 @IBOutlet weak var titleLabel: UILabel!
17 @IBOutlet weak var bgImageView: UIImageView!
18 @IBOutlet weak var bgOverlayView: UIView!
19 @IBOutlet weak var miniatureImageView: UIImageView!
20 @IBOutlet weak var tableView: UITableView!
21 @IBOutlet weak var backButton: UIButton!
22 @IBOutlet weak var toggleListButton: UIButton!
23 @IBOutlet weak var nextButton: UIButton!
24 @IBOutlet weak var prevButton: UIButton!
25 @IBOutlet weak var forwardButton: UIButton!
26 @IBOutlet weak var rewindButton: UIButton!
27 @IBOutlet weak var playPauseButton: UIButton!
28 @IBOutlet weak var trackNumberLabel: UILabel!
29 @IBOutlet weak var trackTitleLabel: UILabel!
30 @IBOutlet weak var trackCurrentTimeLabel: UILabel!
31 @IBOutlet weak var trackTimeLabel: UILabel!
32 @IBOutlet weak var progressSlider: UISlider!
33 @IBOutlet weak var miniatureImageWidthConstraint: NSLayoutConstraint!
34 @IBOutlet weak var trackTitleLabelTopConstraint: NSLayoutConstraint!
36 var bookDetailsModel: BookDetailsModel!
37 var mediaModels: [MediaModel]!
40 static func instance(bookDetailsModel: BookDetailsModel) -> PlayerViewController{
41 let controller = PlayerViewController.instance()
42 controller.bookDetailsModel = bookDetailsModel
43 controller.mediaModels = bookDetailsModel.getAudiobookMediaModels()
47 open override var preferredStatusBarStyle : UIStatusBarStyle {
51 override func viewDidLoad() {
53 tableView.separatorStyle = .none
54 tableView.isHidden = true
56 if UIScreen.main.bounds.size.width == 320 || UIScreen.main.bounds.size.height == 320 {
57 miniatureImageWidthConstraint.constant = 100
60 bgOverlayView.alpha = 0.7
61 bgOverlayView.backgroundColor = bookDetailsModel.bgColor
62 let titleAttributedText = bookDetailsModel.getAttributedAuthorAndTitle(titleFont: UIFont.systemFont(ofSize: 21, weight: .light), descFont: UIFont.systemFont(ofSize: 28, weight: .light))
63 titleLabel.attributedText = titleAttributedText
65 if let bookDetails = PlayerController.shared.currentBookDetails, bookDetails.slug == bookDetailsModel.slug {
66 PlayerController.shared.startOrContinuePlaying(bookDetailsModel: bookDetailsModel, delegate: self)
69 PlayerController.shared.stopAndClear()
70 PlayerController.shared.preparePlayer(bookDetailsModel: bookDetailsModel, delegate: self, trackIndex: 0)
73 if mediaModels.count < 2 {
74 trackNumberLabel.isHidden = true
75 trackNumberLabel.text = ""
76 toggleListButton.isHidden = true
77 trackTitleLabelTopConstraint.constant = 10
80 refreshButtonsVisibility()
82 if let url = bookDetailsModel.getCoverThumbUrl(){
83 ImageDownloader.default.downloadImage(with: url, options: [], progressBlock: nil) {
84 [weak self] (image, error, url, data) in
86 self?.bgImageView.image = image
87 self?.miniatureImageView.image = image
88 PlayerController.shared.setCoverImage(image: image)
94 // ############################################
96 // ############################################
98 private func toggleList() {
99 tableView.isHidden = !tableView.isHidden
102 private func startNextTrack() {
103 PlayerController.shared.playNextAudio()
106 private func startPrevTrack() {
107 PlayerController.shared.playPreviousAudio()
110 //This returns song length
111 private func calculateTimeFromNSTimeInterval(_ duration:TimeInterval) ->(hour: String, minute:String, second:String){
112 let hour_ = abs(Int(duration)/3600)
113 let minute_ = abs(Int((duration/60).truncatingRemainder(dividingBy: 60)))
114 let second_ = abs(Int(duration.truncatingRemainder(dividingBy: 60)))
116 var hour = hour_ > 9 ? "\(hour_)" : "0\(hour_)"
120 let minute = minute_ > 9 ? "\(minute_)" : "0\(minute_)"
121 let second = second_ > 9 ? "\(second_)" : "0\(second_)"
122 return (hour, minute,second)
125 fileprivate func updateCurrentTime(timeInterval: TimeInterval?) {
127 var ti = timeInterval
129 ti = PlayerController.shared.getCurrentTime()
133 let timeIntervalFloat = Float(ti)
134 progressSlider.value = timeIntervalFloat
135 let time = calculateTimeFromNSTimeInterval(ti)
136 if time.hour.count == 0 {
137 trackCurrentTimeLabel.text = "\(time.minute):\(time.second)"
140 trackCurrentTimeLabel.text = "\(time.hour):\(time.minute):\(time.second)"
145 func refreshButtonsVisibility(){
147 prevButton.isHidden = true
148 nextButton.isHidden = true
150 let currentAudiobookIndex = PlayerController.shared.currentAudiobookIndex
151 let allMediaCount = mediaModels.count
153 if currentAudiobookIndex > 0{
154 prevButton.isHidden = false
156 if allMediaCount > currentAudiobookIndex + 1 {
157 nextButton.isHidden = false
161 // ############################################
163 // ############################################
165 @IBAction func backButtonAction(sender: UIButton) {
166 PlayerController.shared.delegate = nil
167 navigationController?.popViewController(animated: true)
170 @IBAction func toggleListButtonAction(sender: UIButton) {
174 @IBAction func nextButtonAction(sender: UIButton) {
175 PlayerController.shared.playNextAudio()
178 @IBAction func prevButtonAction(sender: UIButton) {
179 PlayerController.shared.playPreviousAudio()
182 @IBAction func forwardButtonAction(sender: UIButton) {
183 PlayerController.shared.forward()
186 @IBAction func rewindButtonAction(sender: UIButton) {
187 PlayerController.shared.rewind()
190 @IBAction func playPauseButtonAction(sender: UIButton) {
191 let player = PlayerController.shared
192 if player.isPlaying() {
193 player.pauseAudioPlayer()
196 if player.audioPlayer == nil {
197 player.startOrContinuePlaying(bookDetailsModel: bookDetailsModel, delegate: self)
203 playPauseButton.setImage(player.isPlaying() ? #imageLiteral(resourceName: "player_controls_pause") : #imageLiteral(resourceName: "player_controls_play"), for: .normal)
206 @IBAction func progressSliderAction(sender: UISlider) {
207 PlayerController.shared.changeTime(timeInterval: TimeInterval(sender.value))
211 extension PlayerViewController: UITableViewDataSource {
212 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
213 return mediaModels.count
216 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
217 let cell = tableView.dequeueReusableCell(withIdentifier: "PlayerItemTableViewCell", for: indexPath) as! PlayerItemTableViewCell
218 let isSelected = PlayerController.shared.currentAudiobookIndex == indexPath.row
219 cell.setup(mediaModel: mediaModels[indexPath.row], isPlaying: isSelected)
224 extension PlayerViewController: UITableViewDelegate {
225 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
226 if mediaModels.count > indexPath.row {
228 PlayerController.shared.startPlaying(bookDetailsModel: bookDetailsModel, delegate: self, trackIndex: indexPath.row)
233 extension PlayerViewController: PlayerControllerDelegate {
235 func playerControllerDelegateTrackChanged() {
237 let player = PlayerController.shared
238 progressSlider.maximumValue = Float(player.audioLength)
240 updateCurrentTime(timeInterval: player.getCurrentTime())
241 trackNumberLabel.text = String(format: "player_chapter_number".localized, player.currentAudiobookIndex + 1)
243 if let currentModel = player.getCurentAudiobookMediaModel() {
244 trackTitleLabel.text = currentModel.name
245 let time = calculateTimeFromNSTimeInterval(player.audioLength)
246 if time.hour.count == 0 {
247 trackTimeLabel.text = "\(time.minute):\(time.second)"
250 trackTimeLabel.text = "\(time.hour):\(time.minute):\(time.second)"
254 playPauseButton.setImage(player.isPlaying() ? #imageLiteral(resourceName: "player_controls_pause") : #imageLiteral(resourceName: "player_controls_play"), for: .normal)
256 let newSelectedIndex = IndexPath(row: PlayerController.shared.currentAudiobookIndex, section: 0)
257 tableView.selectRow(at: newSelectedIndex, animated: true, scrollPosition: .middle)
259 refreshButtonsVisibility()
262 func playerControllerDelegateUpdatePlayerProgress(timeInterval: TimeInterval) {
263 updateCurrentTime(timeInterval: timeInterval)
266 func playerControllerDelegatePlayStateChanged() {
267 playPauseButton.setImage(PlayerController.shared.isPlaying() ? #imageLiteral(resourceName: "player_controls_pause") : #imageLiteral(resourceName: "player_controls_play"), for: .normal)