// // QueueController.swift // Persephone // // Created by Daniel Barber on 2019/2/01. // Copyright © 2019 Dan Barber. All rights reserved. // import Cocoa class QueueViewController: NSViewController, NSOutlineViewDataSource, NSOutlineViewDelegate { struct SongItem { var song: MPDClient.Song var queuePos: Int var isPlaying: Bool } var queue: [SongItem] = [] var queuePos: Int = -1 var queueIcon: NSImage? = nil let systemFontRegular = NSFont.systemFont(ofSize: 13, weight: .regular) let systemFontBold = NSFont.systemFont(ofSize: 13, weight: .bold) let playIcon = NSImage(named: "playButton") let pauseIcon = NSImage(named: "pauseButton") override func viewDidLoad() { super.viewDidLoad() queueView.columnAutoresizingStyle = .sequentialColumnAutoresizingStyle NotificationCenter.default.addObserver( self, selector: #selector(stateChanged(_:)), name: Notification.stateChanged, object: AppDelegate.mpdClient ) NotificationCenter.default.addObserver( self, selector: #selector(queueChanged(_:)), name: Notification.queueChanged, object: AppDelegate.mpdClient ) NotificationCenter.default.addObserver( self, selector: #selector(queuePosChanged(_:)), name: Notification.queuePosChanged, object: AppDelegate.mpdClient ) } @IBAction func playTrack(_ sender: Any) { guard let view = sender as? NSOutlineView else { return } let queuePos = view.selectedRow - 1 if queuePos >= 0 { AppDelegate.mpdClient.playTrack(queuePos: queuePos) } } @objc func stateChanged(_ notification: Notification) { guard let state = notification.userInfo?[Notification.stateKey] as? MPDClient.Status.State else { return } setQueueIcon(state) } @objc func queueChanged(_ notification: Notification) { guard let queue = notification.userInfo?[Notification.queueKey] as? [MPDClient.Song] else { return } var newQueue: [SongItem] = [] for (index, mpdSong) in queue.enumerated() { let songItem = SongItem(song: mpdSong, queuePos: index, isPlaying: index == queuePos) newQueue.append(songItem) } self.queue = newQueue queueView.reloadData() } @objc func queuePosChanged(_ notification: Notification) { guard let queuePos = notification.userInfo?[Notification.queuePosKey] as? Int else { return } let oldSongRowPos = self.queuePos let newSongRowPos = queuePos self.queuePos = queuePos setQueuePos(oldSongRowPos: oldSongRowPos, newSongRowPos: newSongRowPos) queueView.reloadData() } func setQueueIcon(_ state: MPDClient.Status.State) { switch state { case .playing: self.queueIcon = playIcon case .paused: self.queueIcon = pauseIcon default: self.queueIcon = nil } } func setQueuePos(oldSongRowPos: Int, newSongRowPos: Int) { if oldSongRowPos >= 0 { queue[oldSongRowPos].isPlaying = false } if newSongRowPos >= 0 { queue[newSongRowPos].isPlaying = true } } func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int { return queue.count + 1 } func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool { return false } func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any { if index > 0 { return queue[index - 1] } else { return false } } func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? { if let songItem = item as? SongItem { switch tableColumn?.identifier.rawValue { case "songTitleColumn": let cellView = outlineView.makeView( withIdentifier: .queueSongTitle, owner: self ) as! NSTableCellView cellView.textField?.stringValue = songItem.song.getTag(.title) if songItem.isPlaying { cellView.textField?.font = systemFontBold cellView.imageView?.image = self.queueIcon } else { cellView.textField?.font = systemFontRegular cellView.imageView?.image = nil } return cellView case "songArtistColumn": let cellView = outlineView.makeView( withIdentifier: .queueSongArtist, owner: self ) as! NSTableCellView cellView.textField?.stringValue = songItem.song.getTag(.artist) if songItem.isPlaying { cellView.textField?.font = systemFontBold } else { cellView.textField?.font = systemFontRegular } return cellView default: return nil } } else { if tableColumn?.identifier.rawValue == "songTitleColumn" { let cellView = outlineView.makeView( withIdentifier: .queueHeading, owner: self ) as! NSTableCellView cellView.textField?.stringValue = "QUEUE" return cellView } else { return nil } } } func outlineView( _ outlineView: NSOutlineView, selectionIndexesForProposedSelection proposedSelectionIndexes: IndexSet ) -> IndexSet { if proposedSelectionIndexes.contains(0) { return IndexSet() } else { return proposedSelectionIndexes } } @IBOutlet var queueView: NSOutlineView! }