mirror of
https://github.com/danbee/persephone
synced 2025-03-04 08:39:11 +00:00
Compare commits
3 Commits
cda2ded9b2
...
170f235547
| Author | SHA1 | Date | |
|---|---|---|---|
| 170f235547 | |||
| 779d365d8a | |||
| 4fc18711b1 |
@ -3,6 +3,7 @@
|
|||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="macosx"/>
|
<deployment identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
|
||||||
|
<capability name="System colors introduced in macOS 10.14" minToolsVersion="10.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
@ -778,7 +779,7 @@
|
|||||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||||
<tableColumns>
|
<tableColumns>
|
||||||
<tableColumn identifier="songTitleColumn" width="222" minWidth="128" maxWidth="1000" id="0Co-uF-CCB">
|
<tableColumn identifier="songTitleColumn" width="222" minWidth="128" maxWidth="1000" id="0Co-uF-CCB">
|
||||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
|
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Title">
|
||||||
<font key="font" metaFont="smallSystem"/>
|
<font key="font" metaFont="smallSystem"/>
|
||||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||||
@ -799,7 +800,7 @@
|
|||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="QUEUE" id="Mqf-uh-ibl">
|
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="QUEUE" id="Mqf-uh-ibl">
|
||||||
<font key="font" metaFont="smallSystemBold"/>
|
<font key="font" metaFont="smallSystemBold"/>
|
||||||
<color key="textColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="controlAccentColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||||
</textFieldCell>
|
</textFieldCell>
|
||||||
</textField>
|
</textField>
|
||||||
@ -814,7 +815,7 @@
|
|||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" constant="17" id="UFf-Fg-9Qg"/>
|
<constraint firstAttribute="width" constant="17" id="UFf-Fg-9Qg"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<imageCell key="cell" refusesFirstResponder="YES" imageScaling="proportionallyDown" image="NSActionTemplate" id="ckK-gW-Vhx"/>
|
<imageCell key="cell" refusesFirstResponder="YES" imageScaling="proportionallyDown" image="playButton" id="ckK-gW-Vhx"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="i0h-bn-auJ">
|
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="i0h-bn-auJ">
|
||||||
<rect key="frame" x="25" y="0.0" width="197" height="17"/>
|
<rect key="frame" x="25" y="0.0" width="197" height="17"/>
|
||||||
@ -841,7 +842,7 @@
|
|||||||
</prototypeCellViews>
|
</prototypeCellViews>
|
||||||
</tableColumn>
|
</tableColumn>
|
||||||
<tableColumn identifier="songArtistColumn" width="222" minWidth="128" maxWidth="1000" id="SPM-QP-DX8">
|
<tableColumn identifier="songArtistColumn" width="222" minWidth="128" maxWidth="1000" id="SPM-QP-DX8">
|
||||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left">
|
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Artist">
|
||||||
<font key="font" metaFont="smallSystem"/>
|
<font key="font" metaFont="smallSystem"/>
|
||||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
|||||||
@ -73,6 +73,7 @@ class MPDClient {
|
|||||||
|
|
||||||
self.delegate?.didUpdateState(mpdClient: self, state: self.status!.state())
|
self.delegate?.didUpdateState(mpdClient: self, state: self.status!.state())
|
||||||
self.delegate?.didUpdateQueue(mpdClient: self, queue: self.queue)
|
self.delegate?.didUpdateQueue(mpdClient: self, queue: self.queue)
|
||||||
|
self.delegate?.didUpdateQueuePos(mpdClient: self, song: self.status!.song())
|
||||||
idle()
|
idle()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +191,7 @@ class MPDClient {
|
|||||||
if mpdIdle.contains(.player) {
|
if mpdIdle.contains(.player) {
|
||||||
self.fetchStatus()
|
self.fetchStatus()
|
||||||
self.delegate?.didUpdateState(mpdClient: self, state: self.status!.state())
|
self.delegate?.didUpdateState(mpdClient: self, state: self.status!.state())
|
||||||
|
self.delegate?.didUpdateQueuePos(mpdClient: self, song: self.status!.song())
|
||||||
}
|
}
|
||||||
if !mpdIdle.isEmpty {
|
if !mpdIdle.isEmpty {
|
||||||
self.idle()
|
self.idle()
|
||||||
|
|||||||
@ -11,6 +11,12 @@ import mpdclient
|
|||||||
|
|
||||||
class QueueController: NSViewController, NSOutlineViewDataSource, NSOutlineViewDelegate {
|
class QueueController: NSViewController, NSOutlineViewDataSource, NSOutlineViewDelegate {
|
||||||
var queue: [MPDClient.Song] = []
|
var queue: [MPDClient.Song] = []
|
||||||
|
var queuePos: Int32 = -1
|
||||||
|
|
||||||
|
struct SongItem {
|
||||||
|
var song: MPDClient.Song
|
||||||
|
var queuePos: Int
|
||||||
|
}
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
@ -23,6 +29,13 @@ class QueueController: NSViewController, NSOutlineViewDataSource, NSOutlineViewD
|
|||||||
name: MPDClient.queueChanged,
|
name: MPDClient.queueChanged,
|
||||||
object: AppDelegate.mpdClient
|
object: AppDelegate.mpdClient
|
||||||
)
|
)
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(
|
||||||
|
self,
|
||||||
|
selector: #selector(queuePosChanged(_:)),
|
||||||
|
name: MPDClient.queuePosChanged,
|
||||||
|
object: AppDelegate.mpdClient
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func queueChanged(_ notification: Notification) {
|
@objc func queueChanged(_ notification: Notification) {
|
||||||
@ -34,6 +47,33 @@ class QueueController: NSViewController, NSOutlineViewDataSource, NSOutlineViewD
|
|||||||
queueView.reloadData()
|
queueView.reloadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func queuePosChanged(_ notification: Notification) {
|
||||||
|
guard let queuePos = notification.userInfo?[MPDClient.queuePosKey] as? Int32
|
||||||
|
else { return }
|
||||||
|
|
||||||
|
if self.queuePos > -1 {
|
||||||
|
let oldSongRow = queueView.rowView(atRow: Int(self.queuePos + 1), makeIfNecessary: true)
|
||||||
|
let oldSongTitleCell = oldSongRow?.view(atColumn: 0) as! NSTableCellView
|
||||||
|
let oldSongArtistCell = oldSongRow?.view(atColumn: 1) as! NSTableCellView
|
||||||
|
oldSongTitleCell.textField?.font = NSFont.systemFont(ofSize: 13, weight: .regular)
|
||||||
|
oldSongArtistCell.textField?.font = NSFont.systemFont(ofSize: 13, weight: .regular)
|
||||||
|
}
|
||||||
|
|
||||||
|
let oldQueuePos = self.queuePos
|
||||||
|
self.queuePos = queuePos
|
||||||
|
|
||||||
|
let songRow = queueView.rowView(atRow: Int(self.queuePos + 1), makeIfNecessary: true)
|
||||||
|
let songTitleCell = songRow?.view(atColumn: 0) as! NSTableCellView
|
||||||
|
let songArtistCell = songRow?.view(atColumn: 1) as! NSTableCellView
|
||||||
|
songTitleCell.textField?.font = NSFont.systemFont(ofSize: 13, weight: .bold)
|
||||||
|
songArtistCell.textField?.font = NSFont.systemFont(ofSize: 13, weight: .bold)
|
||||||
|
|
||||||
|
queueView.reloadData(
|
||||||
|
forRowIndexes: [Int(oldQueuePos + 1), Int(queuePos + 1)],
|
||||||
|
columnIndexes: [0, 1]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
|
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
|
||||||
return queue.count + 1
|
return queue.count + 1
|
||||||
}
|
}
|
||||||
@ -44,31 +84,36 @@ class QueueController: NSViewController, NSOutlineViewDataSource, NSOutlineViewD
|
|||||||
|
|
||||||
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
|
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
|
||||||
if index > 0 {
|
if index > 0 {
|
||||||
return queue[index - 1]
|
return SongItem(song: queue[index - 1], queuePos: index - 1)
|
||||||
} else {
|
} else {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
|
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
|
||||||
if let song = item as? MPDClient.Song {
|
if let songItem = item as? SongItem {
|
||||||
switch tableColumn?.identifier.rawValue {
|
switch tableColumn?.identifier.rawValue {
|
||||||
case "songTitleColumn":
|
case "songTitleColumn":
|
||||||
let cellView = outlineView.makeView(
|
let cellView = outlineView.makeView(
|
||||||
withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "songTitleCell"),
|
withIdentifier: NSUserInterfaceItemIdentifier("songTitleCell"),
|
||||||
owner: self
|
owner: self
|
||||||
) as! NSTableCellView
|
) as! NSTableCellView
|
||||||
|
|
||||||
cellView.textField?.stringValue = song.getTag(MPD_TAG_TITLE)
|
cellView.textField?.stringValue = songItem.song.getTag(MPD_TAG_TITLE)
|
||||||
|
if songItem.queuePos == self.queuePos {
|
||||||
|
cellView.imageView?.image = NSImage(named: NSImage.Name("playButton"))
|
||||||
|
} else {
|
||||||
|
cellView.imageView?.image = nil
|
||||||
|
}
|
||||||
|
|
||||||
return cellView
|
return cellView
|
||||||
case "songArtistColumn":
|
case "songArtistColumn":
|
||||||
let cellView = outlineView.makeView(
|
let cellView = outlineView.makeView(
|
||||||
withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "songArtistCell"),
|
withIdentifier: NSUserInterfaceItemIdentifier("songArtistCell"),
|
||||||
owner: self
|
owner: self
|
||||||
) as! NSTableCellView
|
) as! NSTableCellView
|
||||||
|
|
||||||
cellView.textField?.stringValue = song.getTag(MPD_TAG_ARTIST)
|
cellView.textField?.stringValue = songItem.song.getTag(MPD_TAG_ARTIST)
|
||||||
|
|
||||||
return cellView
|
return cellView
|
||||||
default:
|
default:
|
||||||
@ -77,7 +122,7 @@ class QueueController: NSViewController, NSOutlineViewDataSource, NSOutlineViewD
|
|||||||
} else {
|
} else {
|
||||||
if tableColumn?.identifier.rawValue == "songTitleColumn" {
|
if tableColumn?.identifier.rawValue == "songTitleColumn" {
|
||||||
let cellView = outlineView.makeView(
|
let cellView = outlineView.makeView(
|
||||||
withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "queueHeadingCell"),
|
withIdentifier: NSUserInterfaceItemIdentifier("queueHeadingCell"),
|
||||||
owner: self
|
owner: self
|
||||||
) as! NSTableCellView
|
) as! NSTableCellView
|
||||||
|
|
||||||
|
|||||||
@ -43,9 +43,9 @@ class WindowController: NSWindowController {
|
|||||||
transportControls.setEnabled([MPD_STATE_PLAY, MPD_STATE_PAUSE].contains(state), forSegment: 3)
|
transportControls.setEnabled([MPD_STATE_PLAY, MPD_STATE_PAUSE].contains(state), forSegment: 3)
|
||||||
|
|
||||||
if [MPD_STATE_PAUSE, MPD_STATE_STOP, MPD_STATE_UNKNOWN].contains(state) {
|
if [MPD_STATE_PAUSE, MPD_STATE_STOP, MPD_STATE_UNKNOWN].contains(state) {
|
||||||
transportControls.setImage(NSImage(named: NSImage.Name(rawValue: "playButton")), forSegment: 1)
|
transportControls.setImage(NSImage(named: NSImage.Name("playButton")), forSegment: 1)
|
||||||
} else {
|
} else {
|
||||||
transportControls.setImage(NSImage(named: NSImage.Name(rawValue: "pauseButton")), forSegment: 1)
|
transportControls.setImage(NSImage(named: NSImage.Name("pauseButton")), forSegment: 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
An MPD client for macOS, written in Swift.
|
An MPD client for macOS, written in Swift.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
Run `bin/setup` before opening the Xcode project.
|
Run `bin/setup` before opening the Xcode project.
|
||||||
|
|||||||
BIN
Resources/screenshot.png
Normal file
BIN
Resources/screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 73 KiB |
Loading…
Reference in New Issue
Block a user