149 lines
5.4 KiB
Swift
149 lines
5.4 KiB
Swift
//
|
|
// NowPlayingItem.swift
|
|
// Underbar
|
|
//
|
|
// Created by Shadowfacts on 7/13/19.
|
|
// Copyright © 2019 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import Cocoa
|
|
import MediaToolbox
|
|
|
|
class NowPlayingItem: NSCustomTouchBarItem {
|
|
|
|
var nowPlayingClientID: String?
|
|
var nowPlayingTitle: String?
|
|
var nowPlayingArtist: String?
|
|
var nowPlayingAlbum: String?
|
|
var nowPlayingArtwork: Data?
|
|
|
|
var button: NSButton!
|
|
|
|
var lastPressTime: Date? = nil
|
|
var multiPressCount: Int = 0
|
|
var multiPressWorkItem: DispatchWorkItem? = nil
|
|
|
|
override init(identifier: NSTouchBarItem.Identifier) {
|
|
super.init(identifier: identifier)
|
|
|
|
button = NSButton(title: "Test\nline 2", target: self, action: #selector(buttonPressed))
|
|
button.alignment = .left
|
|
|
|
button.widthAnchor.constraint(equalToConstant: 200).isActive = true
|
|
|
|
let longPressRecognizer = NSPressGestureRecognizer(target: self, action: #selector(buttonLongPressed))
|
|
longPressRecognizer.allowedTouchTypes = .direct
|
|
button.addGestureRecognizer(longPressRecognizer)
|
|
|
|
view = button
|
|
|
|
MRMediaRemoteRegisterForNowPlayingNotifications(.global(qos: .utility))
|
|
registerForNotifications()
|
|
|
|
updateMediaInfo()
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func registerForNotifications() {
|
|
NotificationCenter.default.addObserver(self, selector: #selector(updateMediaInfo), name: .init(kMRMediaRemoteNowPlayingApplicationClientStateDidChange), object: nil)
|
|
NotificationCenter.default.addObserver(self, selector: #selector(updateMediaInfo), name: .mrNowPlayingPlaybackQueueChanged, object: nil)
|
|
NotificationCenter.default.addObserver(self, selector: #selector(updateMediaInfo), name: .mrNowPlayingPlaybackQueueChanged, object: nil)
|
|
NotificationCenter.default.addObserver(self, selector: #selector(updateMediaInfo), name: .mrMediaRemoteNowPlayingApplicationIsPlayingDidChange, object: nil)
|
|
}
|
|
|
|
@objc func updateMediaInfo() {
|
|
MRMediaRemoteGetNowPlayingInfo(.main) { [weak self] (info) in
|
|
guard let self = self, let info = info else { return }
|
|
|
|
self.nowPlayingTitle = info[kMRMediaRemoteNowPlayingInfoTitle] as? String
|
|
self.nowPlayingArtist = info[kMRMediaRemoteNowPlayingInfoArtist] as? String
|
|
self.nowPlayingAlbum = info[kMRMediaRemoteNowPlayingInfoAlbum] as? String
|
|
self.nowPlayingArtwork = info[kMRMediaRemoteNowPlayingInfoArtworkData] as? Data
|
|
|
|
self.updateButtonTitle()
|
|
self.updateButtonImage()
|
|
}
|
|
|
|
MRMediaRemoteGetNowPlayingClient(.main) { (client) in
|
|
guard let client = client else {
|
|
self.nowPlayingClientID = nil
|
|
return
|
|
}
|
|
self.nowPlayingClientID = MRNowPlayingClientGetBundleIdentifier(client)
|
|
}
|
|
}
|
|
|
|
func updateButtonTitle() {
|
|
let attributedStr = NSMutableAttributedString()
|
|
|
|
|
|
|
|
let line1 = NSAttributedString(string: nowPlayingTitle ?? "Unknown")
|
|
attributedStr.append(line1)
|
|
attributedStr.setAttributes([.font: NSFont.systemFont(ofSize: 12)], range: NSRange(location: 0, length: line1.length))
|
|
|
|
attributedStr.append(NSAttributedString(string: "\n"))
|
|
|
|
let line2 = NSAttributedString(string: (nowPlayingArtist ?? "Unknown") + " | " + (nowPlayingAlbum ?? "Unknown"))
|
|
attributedStr.append(line2)
|
|
attributedStr.setAttributes([.font: NSFont.systemFont(ofSize: 10)], range: NSRange(location: line1.length + 1, length: line2.length))
|
|
|
|
button.attributedTitle = attributedStr
|
|
}
|
|
|
|
func updateButtonImage() {
|
|
// todo: custom spotify artwork helper
|
|
if let data = nowPlayingArtwork,
|
|
let image = NSImage(data: data) {
|
|
button.image = image
|
|
button.imagePosition = .imageLeft
|
|
} else {
|
|
button.image = nil
|
|
}
|
|
}
|
|
|
|
@objc func buttonPressed() {
|
|
if let lastPressTime = lastPressTime,
|
|
lastPressTime.timeIntervalSinceNow < 0.2 {
|
|
multiPressCount += 1
|
|
multiPressWorkItem?.cancel()
|
|
} else {
|
|
self.lastPressTime = Date()
|
|
multiPressCount = 1
|
|
}
|
|
|
|
multiPressWorkItem = DispatchWorkItem {
|
|
self.handleMultiPress(presses: self.multiPressCount)
|
|
self.lastPressTime = nil
|
|
self.multiPressCount = 0
|
|
self.multiPressWorkItem = nil
|
|
}
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2, execute: multiPressWorkItem!)
|
|
|
|
}
|
|
|
|
func handleMultiPress(presses: Int) {
|
|
switch presses {
|
|
case 1:
|
|
MRMediaRemoteSendCommand(kMRTogglePlayPause, nil)
|
|
case 2:
|
|
MRMediaRemoteSendCommand(kMRNextTrack, nil)
|
|
case 3:
|
|
MRMediaRemoteSendCommand(kMRPreviousTrack, nil)
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
|
|
@objc func buttonLongPressed(recognizer: NSPressGestureRecognizer) {
|
|
if recognizer.state == .began,
|
|
let nowPlayingClientID = nowPlayingClientID {
|
|
NSWorkspace.shared.launchApplication(withBundleIdentifier: nowPlayingClientID, options: .default, additionalEventParamDescriptor: nil, launchIdentifier: nil)
|
|
}
|
|
}
|
|
|
|
}
|