mirror of
https://github.com/danbee/persephone
synced 2025-03-04 08:39:11 +00:00
Show list of artists
This commit is contained in:
parent
1e7fd2f18c
commit
89320037b7
@ -119,6 +119,12 @@
|
|||||||
E4E96D13233E630800AFD36F /* PMKFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = E4E96D12233E630800AFD36F /* PMKFoundation */; };
|
E4E96D13233E630800AFD36F /* PMKFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = E4E96D12233E630800AFD36F /* PMKFoundation */; };
|
||||||
E4EB2379220F10B8008C70C0 /* MPDPair.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4EB2378220F10B8008C70C0 /* MPDPair.swift */; };
|
E4EB2379220F10B8008C70C0 /* MPDPair.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4EB2378220F10B8008C70C0 /* MPDPair.swift */; };
|
||||||
E4EB237B220F7CF1008C70C0 /* MPDAlbum.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4EB237A220F7CF1008C70C0 /* MPDAlbum.swift */; };
|
E4EB237B220F7CF1008C70C0 /* MPDAlbum.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4EB237A220F7CF1008C70C0 /* MPDAlbum.swift */; };
|
||||||
|
E4F26F732341166200D45FF9 /* ArtistDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F26F722341166200D45FF9 /* ArtistDataSource.swift */; };
|
||||||
|
E4F26F75234117D600D45FF9 /* ArtistItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F26F74234117D600D45FF9 /* ArtistItemView.swift */; };
|
||||||
|
E4F26F7723411AE300D45FF9 /* ArtistListActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F26F7623411AE300D45FF9 /* ArtistListActions.swift */; };
|
||||||
|
E4F26F7923411B1500D45FF9 /* ArtistReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F26F7823411B1500D45FF9 /* ArtistReducer.swift */; };
|
||||||
|
E4F26F7B23411D5400D45FF9 /* MPDClient+Artist.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F26F7A23411D5400D45FF9 /* MPDClient+Artist.swift */; };
|
||||||
|
E4F26F7D2341441C00D45FF9 /* ArtistViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F26F7C2341441C00D45FF9 /* ArtistViewLayout.swift */; };
|
||||||
E4F6B460221E119B00ACF42A /* QueueDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F6B45F221E119B00ACF42A /* QueueDataSource.swift */; };
|
E4F6B460221E119B00ACF42A /* QueueDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F6B45F221E119B00ACF42A /* QueueDataSource.swift */; };
|
||||||
E4F6B463221E125900ACF42A /* QueueItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F6B462221E125900ACF42A /* QueueItem.swift */; };
|
E4F6B463221E125900ACF42A /* QueueItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F6B462221E125900ACF42A /* QueueItem.swift */; };
|
||||||
E4F6B467221E233200ACF42A /* AlbumDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F6B466221E233200ACF42A /* AlbumDataSource.swift */; };
|
E4F6B467221E233200ACF42A /* AlbumDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F6B466221E233200ACF42A /* AlbumDataSource.swift */; };
|
||||||
@ -317,6 +323,12 @@
|
|||||||
E4E8CC9922075D370024217A /* MPDSong.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDSong.swift; sourceTree = "<group>"; };
|
E4E8CC9922075D370024217A /* MPDSong.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDSong.swift; sourceTree = "<group>"; };
|
||||||
E4EB2378220F10B8008C70C0 /* MPDPair.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDPair.swift; sourceTree = "<group>"; };
|
E4EB2378220F10B8008C70C0 /* MPDPair.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDPair.swift; sourceTree = "<group>"; };
|
||||||
E4EB237A220F7CF1008C70C0 /* MPDAlbum.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDAlbum.swift; sourceTree = "<group>"; };
|
E4EB237A220F7CF1008C70C0 /* MPDAlbum.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDAlbum.swift; sourceTree = "<group>"; };
|
||||||
|
E4F26F722341166200D45FF9 /* ArtistDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArtistDataSource.swift; sourceTree = "<group>"; };
|
||||||
|
E4F26F74234117D600D45FF9 /* ArtistItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArtistItemView.swift; sourceTree = "<group>"; };
|
||||||
|
E4F26F7623411AE300D45FF9 /* ArtistListActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArtistListActions.swift; sourceTree = "<group>"; };
|
||||||
|
E4F26F7823411B1500D45FF9 /* ArtistReducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArtistReducer.swift; sourceTree = "<group>"; };
|
||||||
|
E4F26F7A23411D5400D45FF9 /* MPDClient+Artist.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Artist.swift"; sourceTree = "<group>"; };
|
||||||
|
E4F26F7C2341441C00D45FF9 /* ArtistViewLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArtistViewLayout.swift; sourceTree = "<group>"; };
|
||||||
E4F6B45F221E119B00ACF42A /* QueueDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueDataSource.swift; sourceTree = "<group>"; };
|
E4F6B45F221E119B00ACF42A /* QueueDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueDataSource.swift; sourceTree = "<group>"; };
|
||||||
E4F6B462221E125900ACF42A /* QueueItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueItem.swift; sourceTree = "<group>"; };
|
E4F6B462221E125900ACF42A /* QueueItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueItem.swift; sourceTree = "<group>"; };
|
||||||
E4F6B466221E233200ACF42A /* AlbumDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumDataSource.swift; sourceTree = "<group>"; };
|
E4F6B466221E233200ACF42A /* AlbumDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumDataSource.swift; sourceTree = "<group>"; };
|
||||||
@ -448,6 +460,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E41E530A223C033700173814 /* MPDClient+Album.swift */,
|
E41E530A223C033700173814 /* MPDClient+Album.swift */,
|
||||||
|
E4F26F7A23411D5400D45FF9 /* MPDClient+Artist.swift */,
|
||||||
E41E5308223C020400173814 /* MPDClient+Command.swift */,
|
E41E5308223C020400173814 /* MPDClient+Command.swift */,
|
||||||
E41E52FC223BF87300173814 /* MPDClient+Connection.swift */,
|
E41E52FC223BF87300173814 /* MPDClient+Connection.swift */,
|
||||||
E42410B52241B956005ED6DF /* MPDClient+Database.swift */,
|
E42410B52241B956005ED6DF /* MPDClient+Database.swift */,
|
||||||
@ -465,16 +478,17 @@
|
|||||||
E408D3C3220E138B0006D9BE /* Views */ = {
|
E408D3C3220E138B0006D9BE /* Views */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
E43AC1F722C7065A001E483C /* AlbumCoverButton.swift */,
|
||||||
E4A3A6A022A457B600EA2C40 /* AlbumDetailSongListView.swift */,
|
E4A3A6A022A457B600EA2C40 /* AlbumDetailSongListView.swift */,
|
||||||
E45878372296173C00586A1C /* AlbumDetailSongRowView.swift */,
|
E45878372296173C00586A1C /* AlbumDetailSongRowView.swift */,
|
||||||
E47E2FD62220720300F747E6 /* AlbumItemView.swift */,
|
E47E2FD62220720300F747E6 /* AlbumItemView.swift */,
|
||||||
|
E4F26F74234117D600D45FF9 /* ArtistItemView.swift */,
|
||||||
|
E4BBD2E823356DC100702C16 /* BrowseViewButton.swift */,
|
||||||
E4B11BB7227538FA0075461B /* CurrentCoverArtView.swift */,
|
E4B11BB7227538FA0075461B /* CurrentCoverArtView.swift */,
|
||||||
E489E3A222B9D31800CA8CBD /* DraggedSongView.swift */,
|
E489E3A222B9D31800CA8CBD /* DraggedSongView.swift */,
|
||||||
E47E2FD222205D2500F747E6 /* MainWindow.swift */,
|
E47E2FD222205D2500F747E6 /* MainWindow.swift */,
|
||||||
E423563F228623D2001216D6 /* QueueSongTitleView.swift */,
|
E423563F228623D2001216D6 /* QueueSongTitleView.swift */,
|
||||||
E4120D6B22AD8139004CB1F8 /* QueueView.swift */,
|
E4120D6B22AD8139004CB1F8 /* QueueView.swift */,
|
||||||
E43AC1F722C7065A001E483C /* AlbumCoverButton.swift */,
|
|
||||||
E4BBD2E823356DC100702C16 /* BrowseViewButton.swift */,
|
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -560,6 +574,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E47E2FE42220AA0700F747E6 /* AlbumViewLayout.swift */,
|
E47E2FE42220AA0700F747E6 /* AlbumViewLayout.swift */,
|
||||||
|
E4F26F7C2341441C00D45FF9 /* ArtistViewLayout.swift */,
|
||||||
);
|
);
|
||||||
path = Layouts;
|
path = Layouts;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -607,11 +622,12 @@
|
|||||||
E4B11B5F226A4BED0075461B /* Reducers */ = {
|
E4B11B5F226A4BED0075461B /* Reducers */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E4B11B60226A4BFF0075461B /* PlayerReducer.swift */,
|
|
||||||
E4B11B62226A4C510075461B /* AppReducer.swift */,
|
|
||||||
E4B11B74226CC4D30075461B /* QueueReducer.swift */,
|
|
||||||
E4B11B78226D346B0075461B /* AlbumListReducer.swift */,
|
E4B11B78226D346B0075461B /* AlbumListReducer.swift */,
|
||||||
|
E4B11B62226A4C510075461B /* AppReducer.swift */,
|
||||||
|
E4F26F7823411B1500D45FF9 /* ArtistReducer.swift */,
|
||||||
|
E4B11B60226A4BFF0075461B /* PlayerReducer.swift */,
|
||||||
E4FF718F227601B400D4C412 /* PreferencesReducer.swift */,
|
E4FF718F227601B400D4C412 /* PreferencesReducer.swift */,
|
||||||
|
E4B11B74226CC4D30075461B /* QueueReducer.swift */,
|
||||||
E440519D227BB0720090CD6F /* UIReducer.swift */,
|
E440519D227BB0720090CD6F /* UIReducer.swift */,
|
||||||
);
|
);
|
||||||
path = Reducers;
|
path = Reducers;
|
||||||
@ -621,14 +637,14 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E4B11B6B226A5AF50075461B /* Actions */,
|
E4B11B6B226A5AF50075461B /* Actions */,
|
||||||
E4B11B5F226A4BED0075461B /* Reducers */,
|
|
||||||
E4B11B52226928F20075461B /* AppState.swift */,
|
|
||||||
E440519F227BB0AB0090CD6F /* UIState.swift */,
|
|
||||||
E4B11B65226A4F830075461B /* PlayerState.swift */,
|
|
||||||
E4B11B67226A4FA00075461B /* QueueState.swift */,
|
|
||||||
E4B11B69226A4FBC0075461B /* AlbumListState.swift */,
|
E4B11B69226A4FBC0075461B /* AlbumListState.swift */,
|
||||||
E4FF718D2276010E00D4C412 /* PreferencesState.swift */,
|
E4B11B52226928F20075461B /* AppState.swift */,
|
||||||
E4BBD2F223357C0700702C16 /* ArtistListState.swift */,
|
E4BBD2F223357C0700702C16 /* ArtistListState.swift */,
|
||||||
|
E4B11B65226A4F830075461B /* PlayerState.swift */,
|
||||||
|
E4FF718D2276010E00D4C412 /* PreferencesState.swift */,
|
||||||
|
E4B11B67226A4FA00075461B /* QueueState.swift */,
|
||||||
|
E4B11B5F226A4BED0075461B /* Reducers */,
|
||||||
|
E440519F227BB0AB0090CD6F /* UIState.swift */,
|
||||||
);
|
);
|
||||||
path = State;
|
path = State;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -637,9 +653,10 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E4B11BC12275EE410075461B /* AlbumListActions.swift */,
|
E4B11BC12275EE410075461B /* AlbumListActions.swift */,
|
||||||
|
E4F26F7623411AE300D45FF9 /* ArtistListActions.swift */,
|
||||||
E4B11BBD2275EDAA0075461B /* PlayerActions.swift */,
|
E4B11BBD2275EDAA0075461B /* PlayerActions.swift */,
|
||||||
E4B11BBF2275EE150075461B /* QueueActions.swift */,
|
|
||||||
E4FF71912276029000D4C412 /* PreferencesActions.swift */,
|
E4FF71912276029000D4C412 /* PreferencesActions.swift */,
|
||||||
|
E4B11BBF2275EE150075461B /* QueueActions.swift */,
|
||||||
E440519B227BAF2E0090CD6F /* UIActions.swift */,
|
E440519B227BAF2E0090CD6F /* UIActions.swift */,
|
||||||
);
|
);
|
||||||
path = Actions;
|
path = Actions;
|
||||||
@ -707,6 +724,7 @@
|
|||||||
E4F6B466221E233200ACF42A /* AlbumDataSource.swift */,
|
E4F6B466221E233200ACF42A /* AlbumDataSource.swift */,
|
||||||
E4F6B45F221E119B00ACF42A /* QueueDataSource.swift */,
|
E4F6B45F221E119B00ACF42A /* QueueDataSource.swift */,
|
||||||
E43B67AC229194CD007DCF55 /* AlbumTracksDataSource.swift */,
|
E43B67AC229194CD007DCF55 /* AlbumTracksDataSource.swift */,
|
||||||
|
E4F26F722341166200D45FF9 /* ArtistDataSource.swift */,
|
||||||
);
|
);
|
||||||
path = DataSources;
|
path = DataSources;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -930,6 +948,7 @@
|
|||||||
E4B11B68226A4FA00075461B /* QueueState.swift in Sources */,
|
E4B11B68226A4FA00075461B /* QueueState.swift in Sources */,
|
||||||
E4928E0B2218D62A001D4BEA /* CGColor.swift in Sources */,
|
E4928E0B2218D62A001D4BEA /* CGColor.swift in Sources */,
|
||||||
E4BBD2ED2335798E00702C16 /* ArtistViewController.swift in Sources */,
|
E4BBD2ED2335798E00702C16 /* ArtistViewController.swift in Sources */,
|
||||||
|
E4F26F732341166200D45FF9 /* ArtistDataSource.swift in Sources */,
|
||||||
E4D3BFA622B419C000C56F48 /* QueueViewController+NSOutlineViewDelegate.swift in Sources */,
|
E4D3BFA622B419C000C56F48 /* QueueViewController+NSOutlineViewDelegate.swift in Sources */,
|
||||||
E4405192227644340090CD6F /* MPDServerController.swift in Sources */,
|
E4405192227644340090CD6F /* MPDServerController.swift in Sources */,
|
||||||
E4C8B53E22349002009A20F3 /* MPDIdle.swift in Sources */,
|
E4C8B53E22349002009A20F3 /* MPDIdle.swift in Sources */,
|
||||||
@ -950,6 +969,7 @@
|
|||||||
E43B67AD229194CD007DCF55 /* AlbumTracksDataSource.swift in Sources */,
|
E43B67AD229194CD007DCF55 /* AlbumTracksDataSource.swift in Sources */,
|
||||||
E41E52FD223BF87300173814 /* MPDClient+Connection.swift in Sources */,
|
E41E52FD223BF87300173814 /* MPDClient+Connection.swift in Sources */,
|
||||||
E450AD7E222620A10091BED3 /* Album.swift in Sources */,
|
E450AD7E222620A10091BED3 /* Album.swift in Sources */,
|
||||||
|
E4F26F7D2341441C00D45FF9 /* ArtistViewLayout.swift in Sources */,
|
||||||
E408D3B6220DD8970006D9BE /* Notification.swift in Sources */,
|
E408D3B6220DD8970006D9BE /* Notification.swift in Sources */,
|
||||||
E43AC1F822C7065A001E483C /* AlbumCoverButton.swift in Sources */,
|
E43AC1F822C7065A001E483C /* AlbumCoverButton.swift in Sources */,
|
||||||
E45962C62241A78500FC1A1E /* MPDCommand.swift in Sources */,
|
E45962C62241A78500FC1A1E /* MPDCommand.swift in Sources */,
|
||||||
@ -963,6 +983,7 @@
|
|||||||
E4F6B463221E125900ACF42A /* QueueItem.swift in Sources */,
|
E4F6B463221E125900ACF42A /* QueueItem.swift in Sources */,
|
||||||
E4A83BF12221FAA00098FED6 /* PreferencesViewController.swift in Sources */,
|
E4A83BF12221FAA00098FED6 /* PreferencesViewController.swift in Sources */,
|
||||||
E4B11BC22275EE410075461B /* AlbumListActions.swift in Sources */,
|
E4B11BC22275EE410075461B /* AlbumListActions.swift in Sources */,
|
||||||
|
E4F26F7B23411D5400D45FF9 /* MPDClient+Artist.swift in Sources */,
|
||||||
E4B11B61226A4C000075461B /* PlayerReducer.swift in Sources */,
|
E4B11B61226A4C000075461B /* PlayerReducer.swift in Sources */,
|
||||||
E4FF71922276029000D4C412 /* PreferencesActions.swift in Sources */,
|
E4FF71922276029000D4C412 /* PreferencesActions.swift in Sources */,
|
||||||
E489E39922B85D0400CA8CBD /* NSPasteboard.swift in Sources */,
|
E489E39922B85D0400CA8CBD /* NSPasteboard.swift in Sources */,
|
||||||
@ -980,11 +1001,13 @@
|
|||||||
E4B11B75226CC4D30075461B /* QueueReducer.swift in Sources */,
|
E4B11B75226CC4D30075461B /* QueueReducer.swift in Sources */,
|
||||||
E41E5309223C020400173814 /* MPDClient+Command.swift in Sources */,
|
E41E5309223C020400173814 /* MPDClient+Command.swift in Sources */,
|
||||||
E4BBD2E923356DC100702C16 /* BrowseViewButton.swift in Sources */,
|
E4BBD2E923356DC100702C16 /* BrowseViewButton.swift in Sources */,
|
||||||
|
E4F26F7923411B1500D45FF9 /* ArtistReducer.swift in Sources */,
|
||||||
E4B11B73226A6C770075461B /* TrackTimer.swift in Sources */,
|
E4B11B73226A6C770075461B /* TrackTimer.swift in Sources */,
|
||||||
E4BBD2EB2335735500702C16 /* BrowseController.swift in Sources */,
|
E4BBD2EB2335735500702C16 /* BrowseController.swift in Sources */,
|
||||||
E44051942278765A0090CD6F /* App.swift in Sources */,
|
E44051942278765A0090CD6F /* App.swift in Sources */,
|
||||||
E4B11B79226D346B0075461B /* AlbumListReducer.swift in Sources */,
|
E4B11B79226D346B0075461B /* AlbumListReducer.swift in Sources */,
|
||||||
E47E2FE52220AA0700F747E6 /* AlbumViewLayout.swift in Sources */,
|
E47E2FE52220AA0700F747E6 /* AlbumViewLayout.swift in Sources */,
|
||||||
|
E4F26F75234117D600D45FF9 /* ArtistItemView.swift in Sources */,
|
||||||
E41E52FF223BF95E00173814 /* MPDClient+Transport.swift in Sources */,
|
E41E52FF223BF95E00173814 /* MPDClient+Transport.swift in Sources */,
|
||||||
E47E2FD322205D2500F747E6 /* MainWindow.swift in Sources */,
|
E47E2FD322205D2500F747E6 /* MainWindow.swift in Sources */,
|
||||||
E47E2FD122205C4600F747E6 /* MainSplitViewController.swift in Sources */,
|
E47E2FD122205C4600F747E6 /* MainSplitViewController.swift in Sources */,
|
||||||
@ -999,6 +1022,7 @@
|
|||||||
E408D3BE220E03EE0006D9BE /* RawRepresentable.swift in Sources */,
|
E408D3BE220E03EE0006D9BE /* RawRepresentable.swift in Sources */,
|
||||||
E4B11B66226A4F830075461B /* PlayerState.swift in Sources */,
|
E4B11B66226A4F830075461B /* PlayerState.swift in Sources */,
|
||||||
E4B11BBE2275EDAA0075461B /* PlayerActions.swift in Sources */,
|
E4B11BBE2275EDAA0075461B /* PlayerActions.swift in Sources */,
|
||||||
|
E4F26F7723411AE300D45FF9 /* ArtistListActions.swift in Sources */,
|
||||||
E4FF71942276043A00D4C412 /* MPDServer.swift in Sources */,
|
E4FF71942276043A00D4C412 /* MPDServer.swift in Sources */,
|
||||||
E41E530E223EF4CF00173814 /* CoverArtService+Caching.swift in Sources */,
|
E41E530E223EF4CF00173814 /* CoverArtService+Caching.swift in Sources */,
|
||||||
E4E8CC922204F4B80024217A /* QueueViewController.swift in Sources */,
|
E4E8CC922204F4B80024217A /* QueueViewController.swift in Sources */,
|
||||||
@ -1186,10 +1210,7 @@
|
|||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
DEVELOPMENT_TEAM = BDEE7ZBFZ3;
|
DEVELOPMENT_TEAM = BDEE7ZBFZ3;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||||
"$(inherited)",
|
|
||||||
"$(PROJECT_DIR)/Carthage/Build/Mac",
|
|
||||||
);
|
|
||||||
INFOPLIST_FILE = Persephone/Info.plist;
|
INFOPLIST_FILE = Persephone/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@ -1217,10 +1238,7 @@
|
|||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
DEVELOPMENT_TEAM = BDEE7ZBFZ3;
|
DEVELOPMENT_TEAM = BDEE7ZBFZ3;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||||
"$(inherited)",
|
|
||||||
"$(PROJECT_DIR)/Carthage/Build/Mac",
|
|
||||||
);
|
|
||||||
INFOPLIST_FILE = Persephone/Info.plist;
|
INFOPLIST_FILE = Persephone/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
|
|||||||
@ -15,5 +15,5 @@ struct App {
|
|||||||
static let userNotificationsController = UserNotificationsController()
|
static let userNotificationsController = UserNotificationsController()
|
||||||
static let mpdServerController = MPDServerController()
|
static let mpdServerController = MPDServerController()
|
||||||
static let mpdServerDelegate = MPDServerDelegate()
|
static let mpdServerDelegate = MPDServerDelegate()
|
||||||
static let mpdClient = MPDClient(withDelegate: mpdServerDelegate)
|
static var mpdClient: MPDClient!
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,10 +39,13 @@ class AppDelegate: NSObject,
|
|||||||
func connectToMPDServer() {
|
func connectToMPDServer() {
|
||||||
let mpdServer = App.store.state.preferencesState.mpdServer
|
let mpdServer = App.store.state.preferencesState.mpdServer
|
||||||
|
|
||||||
App.mpdClient.connect(
|
App.mpdClient = MPDClient(
|
||||||
host: mpdServer.hostOrDefault,
|
host: mpdServer.hostOrDefault,
|
||||||
port: mpdServer.portOrDefault
|
port: mpdServer.portOrDefault,
|
||||||
|
withDelegate: App.mpdServerDelegate
|
||||||
)
|
)
|
||||||
|
|
||||||
|
App.mpdClient.connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
func instantiateControllers() {
|
func instantiateControllers() {
|
||||||
|
|||||||
@ -21,6 +21,9 @@ class AlbumViewController: NSViewController,
|
|||||||
$0.select { $0.albumListState }
|
$0.select { $0.albumListState }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(didConnect), name: .didConnect, object: nil)
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(willDisconnect), name: .willDisconnect, object: nil)
|
||||||
|
|
||||||
albumScrollView.postsBoundsChangedNotifications = true
|
albumScrollView.postsBoundsChangedNotifications = true
|
||||||
|
|
||||||
albumCollectionView.dataSource = dataSource
|
albumCollectionView.dataSource = dataSource
|
||||||
@ -51,6 +54,16 @@ class AlbumViewController: NSViewController,
|
|||||||
layout.setScrollPosition()
|
layout.setScrollPosition()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func didConnect() {
|
||||||
|
App.mpdClient.fetchAllAlbums()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func willDisconnect() {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
App.store.dispatch(UpdateAlbumListAction(albums: []))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@IBOutlet var albumScrollView: NSScrollView!
|
@IBOutlet var albumScrollView: NSScrollView!
|
||||||
@IBOutlet var albumCollectionView: NSCollectionView!
|
@IBOutlet var albumCollectionView: NSCollectionView!
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,53 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import AppKit
|
import AppKit
|
||||||
|
import ReSwift
|
||||||
|
import Differ
|
||||||
|
|
||||||
class ArtistViewController: NSViewController {
|
class ArtistViewController: NSViewController {
|
||||||
|
var dataSource = ArtistDataSource()
|
||||||
|
|
||||||
|
@IBOutlet var artistCollectionView: NSCollectionView!
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
App.store.subscribe(self) {
|
||||||
|
$0.select { $0.artistListState }
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(didConnect), name: .didConnect, object: nil)
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(willDisconnect), name: .willDisconnect, object: nil)
|
||||||
|
|
||||||
|
artistCollectionView.dataSource = dataSource
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
App.store.unsubscribe(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func didConnect() {
|
||||||
|
App.mpdClient.fetchAllArtists()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func willDisconnect() {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
App.store.dispatch(UpdateArtistListAction(artists: []))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ArtistViewController: StoreSubscriber {
|
||||||
|
typealias StoreSubscriberStateType = ArtistListState
|
||||||
|
|
||||||
|
func newState(state: StoreSubscriberStateType) {
|
||||||
|
let oldArtists = dataSource.artists
|
||||||
|
|
||||||
|
dataSource.artists = state.artists
|
||||||
|
|
||||||
|
artistCollectionView.animateItemChanges(
|
||||||
|
oldData: oldArtists,
|
||||||
|
newData: dataSource.artists
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,14 +8,13 @@
|
|||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
class ArtistViewItem: NSViewController {
|
class ArtistViewItem: NSCollectionViewItem {
|
||||||
var artist: String?
|
var artist: String?
|
||||||
|
|
||||||
@IBOutlet var artistName: NSTextField!
|
@IBOutlet var artistName: NSTextField!
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
// Do view setup here.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setArtist(_ artist: String) {
|
func setArtist(_ artist: String) {
|
||||||
|
|||||||
@ -11,9 +11,9 @@ import ReSwift
|
|||||||
|
|
||||||
class MPDServerController {
|
class MPDServerController {
|
||||||
init() {
|
init() {
|
||||||
App.store.subscribe(self) {
|
// App.store.subscribe(self) {
|
||||||
$0.select { $0.preferencesState.mpdServer }
|
// $0.select { $0.preferencesState.mpdServer }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,9 +22,6 @@ extension MPDServerController: StoreSubscriber {
|
|||||||
|
|
||||||
func newState(state: MPDServer) {
|
func newState(state: MPDServer) {
|
||||||
App.mpdClient.disconnect()
|
App.mpdClient.disconnect()
|
||||||
App.mpdClient.connect(
|
App.mpdClient.connect()
|
||||||
host: state.hostOrDefault,
|
|
||||||
port: state.portOrDefault
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,12 +9,12 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class MPDServerDelegate: MPDClientDelegate {
|
class MPDServerDelegate: MPDClientDelegate {
|
||||||
func didConnect(mpdClient: MPDClient) {}
|
func didConnect(mpdClient: MPDClient) {
|
||||||
|
NotificationCenter.default.post(name: .didConnect, object: nil)
|
||||||
|
}
|
||||||
|
|
||||||
func willDisconnect(mpdClient: MPDClient) {
|
func willDisconnect(mpdClient: MPDClient) {
|
||||||
DispatchQueue.main.async {
|
NotificationCenter.default.post(name: .willDisconnect, object: nil)
|
||||||
App.store.dispatch(UpdateAlbumListAction(albums: []))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func didUpdateStatus(mpdClient: MPDClient, status: MPDClient.MPDStatus) {
|
func didUpdateStatus(mpdClient: MPDClient, status: MPDClient.MPDStatus) {
|
||||||
@ -52,4 +52,10 @@ class MPDServerDelegate: MPDClientDelegate {
|
|||||||
App.store.dispatch(UpdateAlbumListAction(albums: albums))
|
App.store.dispatch(UpdateAlbumListAction(albums: albums))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func didLoadArtists(mpdClient: MPDClient, artists: [String]) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
App.store.dispatch(UpdateArtistListAction(artists: artists))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,12 +22,19 @@ class QueueViewController: NSViewController {
|
|||||||
$0.select { $0.queueState }
|
$0.select { $0.queueState }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(didConnect), name: .didConnect, object: nil)
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(willDisconnect), name: .willDisconnect, object: nil)
|
||||||
|
|
||||||
queueView.dataSource = dataSource
|
queueView.dataSource = dataSource
|
||||||
queueView.columnAutoresizingStyle = .sequentialColumnAutoresizingStyle
|
queueView.columnAutoresizingStyle = .sequentialColumnAutoresizingStyle
|
||||||
queueView.registerForDraggedTypes([.songPasteboardType, .albumPasteboardType])
|
queueView.registerForDraggedTypes([.songPasteboardType, .albumPasteboardType])
|
||||||
queueView.draggingDestinationFeedbackStyle = .regular
|
queueView.draggingDestinationFeedbackStyle = .regular
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
App.store.unsubscribe(self)
|
||||||
|
}
|
||||||
|
|
||||||
override func keyDown(with event: NSEvent) {
|
override func keyDown(with event: NSEvent) {
|
||||||
switch event.keyCode {
|
switch event.keyCode {
|
||||||
case NSEvent.keyCodeSpace:
|
case NSEvent.keyCodeSpace:
|
||||||
@ -43,6 +50,17 @@ class QueueViewController: NSViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func didConnect() {
|
||||||
|
App.mpdClient.fetchQueue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func willDisconnect() {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
App.store.dispatch(UpdateQueuePosAction(queuePos: -1))
|
||||||
|
App.store.dispatch(UpdateQueueAction(queue: []))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@IBAction func playTrack(_ sender: Any) {
|
@IBAction func playTrack(_ sender: Any) {
|
||||||
let queuePos = queueView.selectedRow - 1
|
let queuePos = queueView.selectedRow - 1
|
||||||
|
|
||||||
|
|||||||
@ -189,7 +189,7 @@ extension WindowController: NSWindowDelegate {
|
|||||||
extension WindowController: StoreSubscriber {
|
extension WindowController: StoreSubscriber {
|
||||||
typealias StoreSubscriberStateType = (playerState: PlayerState, uiState: UIState)
|
typealias StoreSubscriberStateType = (playerState: PlayerState, uiState: UIState)
|
||||||
|
|
||||||
func newState(state: (playerState: PlayerState, uiState: UIState)) {
|
func newState(state: StoreSubscriberStateType) {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.setTransportControlState(state.playerState)
|
self.setTransportControlState(state.playerState)
|
||||||
self.setShuffleRepeatState(state.playerState)
|
self.setShuffleRepeatState(state.playerState)
|
||||||
|
|||||||
27
Persephone/DataSources/ArtistDataSource.swift
Normal file
27
Persephone/DataSources/ArtistDataSource.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// ArtistDataSource.swift
|
||||||
|
// Persephone
|
||||||
|
//
|
||||||
|
// Created by Daniel Barber on 2019/9/29.
|
||||||
|
// Copyright © 2019 Dan Barber. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import AppKit
|
||||||
|
|
||||||
|
class ArtistDataSource: NSObject, NSCollectionViewDataSource {
|
||||||
|
var artists: [String] = []
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||||
|
return artists.count
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
|
||||||
|
let item = collectionView.makeItem(withIdentifier: .artistViewItem, for: indexPath)
|
||||||
|
guard let artistViewItem = item as? ArtistViewItem
|
||||||
|
else { return item }
|
||||||
|
|
||||||
|
artistViewItem.setArtist(artists[indexPath.item])
|
||||||
|
|
||||||
|
return artistViewItem
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,6 +17,7 @@ extension NSUserInterfaceItemIdentifier {
|
|||||||
static let queueSongTitle = NSUserInterfaceItemIdentifier("songTitleCell")
|
static let queueSongTitle = NSUserInterfaceItemIdentifier("songTitleCell")
|
||||||
|
|
||||||
static let albumViewItem = NSUserInterfaceItemIdentifier("AlbumViewItem")
|
static let albumViewItem = NSUserInterfaceItemIdentifier("AlbumViewItem")
|
||||||
|
static let artistViewItem = NSUserInterfaceItemIdentifier("ArtistViewItem")
|
||||||
|
|
||||||
static let discNumber = NSUserInterfaceItemIdentifier("discNumberCell")
|
static let discNumber = NSUserInterfaceItemIdentifier("discNumberCell")
|
||||||
static let trackNumber = NSUserInterfaceItemIdentifier("trackNumberCell")
|
static let trackNumber = NSUserInterfaceItemIdentifier("trackNumberCell")
|
||||||
|
|||||||
@ -8,22 +8,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
extension Notification {
|
extension Notification.Name {
|
||||||
static let didConnect = Name("MPDClientDidConnect")
|
static let didConnect = Notification.Name("MPDClientDidConnect")
|
||||||
static let willDisconnect = Name("MPDClientWillDisconnect")
|
static let willDisconnect = Notification.Name("MPDClientWillDisconnect")
|
||||||
|
|
||||||
static let stateChanged = Name("MPDClientStateChanged")
|
|
||||||
static let timeChanged = Name("MPDClientTimeChanged")
|
|
||||||
static let databaseUpdateStarted = Name("MPDClientDatabaseUpdateStarted")
|
|
||||||
static let databaseUpdateFinished = Name("MPDClientDatabaseUpdateFinished")
|
|
||||||
static let queueChanged = Name("MPDClientQueueChanged")
|
|
||||||
static let queuePosChanged = Name("MPDClientQueuePosChanged")
|
|
||||||
static let loadedAlbums = Name("MPDClientLoadedAlbums")
|
|
||||||
|
|
||||||
static let stateKey = "state"
|
|
||||||
static let queueKey = "queue"
|
|
||||||
static let queuePosKey = "song"
|
|
||||||
static let albumsKey = "albums"
|
|
||||||
static let totalTimeKey = "totalTime"
|
|
||||||
static let elapsedTimeMsKey = "elapsedTimeMs"
|
|
||||||
}
|
}
|
||||||
|
|||||||
22
Persephone/Layouts/ArtistViewLayout.swift
Normal file
22
Persephone/Layouts/ArtistViewLayout.swift
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// ArtistViewLayout.swift
|
||||||
|
// Persephone
|
||||||
|
//
|
||||||
|
// Created by Daniel Barber on 2019/9/29.
|
||||||
|
// Copyright © 2019 Dan Barber. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import AppKit
|
||||||
|
|
||||||
|
class ArtistViewLayout: NSCollectionViewFlowLayout {
|
||||||
|
override func prepare() {
|
||||||
|
super.prepare()
|
||||||
|
|
||||||
|
guard let collectionView = collectionView
|
||||||
|
else { return }
|
||||||
|
|
||||||
|
let width = collectionView.bounds.size.width
|
||||||
|
|
||||||
|
itemSize.width = width
|
||||||
|
}
|
||||||
|
}
|
||||||
38
Persephone/MPDClient/Extensions/MPDClient+Artist.swift
Normal file
38
Persephone/MPDClient/Extensions/MPDClient+Artist.swift
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// MPDClient+Artist.swift
|
||||||
|
// Persephone
|
||||||
|
//
|
||||||
|
// Created by Daniel Barber on 2019/9/29.
|
||||||
|
// Copyright © 2019 Dan Barber. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import mpdclient
|
||||||
|
|
||||||
|
extension MPDClient {
|
||||||
|
func fetchAllArtists() {
|
||||||
|
enqueueCommand(command: .fetchAllArtists)
|
||||||
|
}
|
||||||
|
|
||||||
|
func allArtists() {
|
||||||
|
var artists: [String] = []
|
||||||
|
|
||||||
|
mpd_search_db_tags(self.connection, MPD_TAG_ALBUM_ARTIST)
|
||||||
|
mpd_search_commit(self.connection)
|
||||||
|
|
||||||
|
while let pair = mpd_recv_pair(self.connection) {
|
||||||
|
let pair = MPDPair(pair)
|
||||||
|
|
||||||
|
switch pair.name {
|
||||||
|
case "AlbumArtist":
|
||||||
|
artists.append(pair.value)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
mpd_return_pair(self.connection, pair.pair)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.delegate?.didLoadArtists(mpdClient: self, artists: artists)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -87,6 +87,10 @@ extension MPDClient {
|
|||||||
else { return }
|
else { return }
|
||||||
sendAddAlbumToQueue(album: album, at: queuePos)
|
sendAddAlbumToQueue(album: album, at: queuePos)
|
||||||
|
|
||||||
|
// Artist commands
|
||||||
|
case .fetchAllArtists:
|
||||||
|
allArtists()
|
||||||
|
|
||||||
// Album commands
|
// Album commands
|
||||||
case .fetchAllAlbums:
|
case .fetchAllAlbums:
|
||||||
allAlbums()
|
allAlbums()
|
||||||
@ -107,6 +111,7 @@ extension MPDClient {
|
|||||||
|
|
||||||
albumSongs(for: album, callback: callback)
|
albumSongs(for: album, callback: callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func enqueueCommand(
|
func enqueueCommand(
|
||||||
|
|||||||
@ -10,8 +10,8 @@ import Foundation
|
|||||||
import mpdclient
|
import mpdclient
|
||||||
|
|
||||||
extension MPDClient {
|
extension MPDClient {
|
||||||
func connect(host: String, port: Int) {
|
func makeConnectionOperation(host: String, port: Int) -> BlockOperation {
|
||||||
commandQueue.addOperation { [unowned self] in
|
BlockOperation { [unowned self] in
|
||||||
guard let connection = mpd_connection_new(host, UInt32(port), 10000),
|
guard let connection = mpd_connection_new(host, UInt32(port), 10000),
|
||||||
mpd_connection_get_error(connection) == MPD_ERROR_SUCCESS
|
mpd_connection_get_error(connection) == MPD_ERROR_SUCCESS
|
||||||
else { return }
|
else { return }
|
||||||
@ -24,17 +24,17 @@ extension MPDClient {
|
|||||||
self.connection = connection
|
self.connection = connection
|
||||||
self.status = MPDStatus(status)
|
self.status = MPDStatus(status)
|
||||||
|
|
||||||
self.fetchQueue()
|
|
||||||
self.fetchAllAlbums()
|
|
||||||
self.idle()
|
|
||||||
|
|
||||||
self.delegate?.didConnect(mpdClient: self)
|
self.delegate?.didConnect(mpdClient: self)
|
||||||
self.delegate?.didUpdateStatus(mpdClient: self, status: self.status!)
|
self.delegate?.didUpdateStatus(mpdClient: self, status: self.status!)
|
||||||
self.delegate?.didUpdateQueue(mpdClient: self, queue: self.queue)
|
|
||||||
self.delegate?.didUpdateQueuePos(mpdClient: self, song: self.status!.song)
|
self.idle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func connect() {
|
||||||
|
commandQueue.addOperation(connectionOperation)
|
||||||
|
}
|
||||||
|
|
||||||
func disconnect() {
|
func disconnect() {
|
||||||
guard isConnected else { return }
|
guard isConnected else { return }
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import mpdclient
|
|||||||
|
|
||||||
extension MPDClient {
|
extension MPDClient {
|
||||||
func fetchQueue() {
|
func fetchQueue() {
|
||||||
sendCommand(command: .fetchQueue)
|
enqueueCommand(command: .fetchQueue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearQueue() {
|
func clearQueue() {
|
||||||
@ -54,6 +54,8 @@ extension MPDClient {
|
|||||||
let song = MPDSong(mpdSong)
|
let song = MPDSong(mpdSong)
|
||||||
self.queue.append(song)
|
self.queue.append(song)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.delegate?.didUpdateQueue(mpdClient: self, queue: self.queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendClearQueue() {
|
func sendClearQueue() {
|
||||||
|
|||||||
@ -10,6 +10,8 @@ import Foundation
|
|||||||
import mpdclient
|
import mpdclient
|
||||||
|
|
||||||
class MPDClient {
|
class MPDClient {
|
||||||
|
var connectionOperation: BlockOperation!
|
||||||
|
|
||||||
var delegate: MPDClientDelegate?
|
var delegate: MPDClientDelegate?
|
||||||
|
|
||||||
var connection: OpaquePointer?
|
var connection: OpaquePointer?
|
||||||
@ -20,8 +22,9 @@ class MPDClient {
|
|||||||
|
|
||||||
let commandQueue = OperationQueue()
|
let commandQueue = OperationQueue()
|
||||||
|
|
||||||
init(withDelegate delegate: MPDClientDelegate?) {
|
init(host: String, port: Int, withDelegate delegate: MPDClientDelegate?) {
|
||||||
commandQueue.maxConcurrentOperationCount = 1
|
commandQueue.maxConcurrentOperationCount = 1
|
||||||
self.delegate = delegate
|
self.delegate = delegate
|
||||||
|
self.connectionOperation = makeConnectionOperation(host: host, port: port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,6 +37,9 @@ extension MPDClient {
|
|||||||
case addSongToQueue
|
case addSongToQueue
|
||||||
case addAlbumToQueue
|
case addAlbumToQueue
|
||||||
|
|
||||||
|
// Artist commands
|
||||||
|
case fetchAllArtists
|
||||||
|
|
||||||
// Album commands
|
// Album commands
|
||||||
case fetchAllAlbums
|
case fetchAllAlbums
|
||||||
case playAlbum
|
case playAlbum
|
||||||
|
|||||||
@ -21,4 +21,6 @@ protocol MPDClientDelegate {
|
|||||||
func didUpdateQueuePos(mpdClient: MPDClient, song: Int)
|
func didUpdateQueuePos(mpdClient: MPDClient, song: Int)
|
||||||
|
|
||||||
func didLoadAlbums(mpdClient: MPDClient, albums: [MPDClient.MPDAlbum])
|
func didLoadAlbums(mpdClient: MPDClient, albums: [MPDClient.MPDAlbum])
|
||||||
|
|
||||||
|
func didLoadArtists(mpdClient: MPDClient, artists: [String])
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14868" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="macosx"/>
|
<deployment identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
|
||||||
<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>
|
||||||
<objects>
|
<objects>
|
||||||
@ -59,7 +59,7 @@
|
|||||||
</textFieldCell>
|
</textFieldCell>
|
||||||
</textField>
|
</textField>
|
||||||
<textField identifier="albumArtist" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5Uu-j1-qyT">
|
<textField identifier="albumArtist" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5Uu-j1-qyT">
|
||||||
<rect key="frame" x="8" y="10" width="142" height="17"/>
|
<rect key="frame" x="8" y="10" width="142" height="16"/>
|
||||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" title="Label" id="yZn-e9-zyP">
|
<textFieldCell key="cell" lineBreakMode="truncatingTail" title="Label" id="yZn-e9-zyP">
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14868" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="macosx"/>
|
<deployment identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
|
||||||
<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>
|
||||||
<objects>
|
<objects>
|
||||||
@ -14,12 +14,12 @@
|
|||||||
</customObject>
|
</customObject>
|
||||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||||
<customView id="Hz6-mo-xeY">
|
<customView id="Hz6-mo-xeY" customClass="ArtistItemView" customModule="Persephone" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="497" height="63"/>
|
<rect key="frame" x="0.0" y="0.0" width="497" height="63"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textField identifier="artistName" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="XcT-rc-7KI">
|
<textField identifier="artistName" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="XcT-rc-7KI">
|
||||||
<rect key="frame" x="18" y="21" width="108" height="22"/>
|
<rect key="frame" x="18" y="22" width="108" height="21"/>
|
||||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Artist Name" id="Ojy-kp-TUe">
|
<textFieldCell key="cell" lineBreakMode="clipping" title="Artist Name" id="Ojy-kp-TUe">
|
||||||
<font key="font" metaFont="systemBold" size="18"/>
|
<font key="font" metaFont="systemBold" size="18"/>
|
||||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
@ -33,5 +33,6 @@
|
|||||||
</constraints>
|
</constraints>
|
||||||
<point key="canvasLocation" x="-21.5" y="-20.5"/>
|
<point key="canvasLocation" x="-21.5" y="-20.5"/>
|
||||||
</customView>
|
</customView>
|
||||||
|
<collectionViewItem id="Thj-la-1Au" customClass="ArtistViewItem" customModule="Persephone" customModuleProvider="target"/>
|
||||||
</objects>
|
</objects>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@ -339,7 +339,6 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</window>
|
</window>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="browseViewControl" destination="F8b-3l-HcP" id="a4B-dd-NDE"/>
|
|
||||||
<outlet property="browseViewControls" destination="F8b-3l-HcP" id="AMQ-6B-8Zd"/>
|
<outlet property="browseViewControls" destination="F8b-3l-HcP" id="AMQ-6B-8Zd"/>
|
||||||
<outlet property="databaseUpdatingIndicator" destination="LpV-iM-o6t" id="y0T-eR-ygY"/>
|
<outlet property="databaseUpdatingIndicator" destination="LpV-iM-o6t" id="y0T-eR-ygY"/>
|
||||||
<outlet property="repeatState" destination="OqH-lV-sAg" id="DPC-Ff-Srr"/>
|
<outlet property="repeatState" destination="OqH-lV-sAg" id="DPC-Ff-Srr"/>
|
||||||
@ -882,7 +881,7 @@
|
|||||||
<!--Artist View Controller-->
|
<!--Artist View Controller-->
|
||||||
<scene sceneID="SZb-JU-J7O">
|
<scene sceneID="SZb-JU-J7O">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController id="LpS-90-tby" customClass="ArtistViewController" sceneMemberID="viewController">
|
<viewController id="LpS-90-tby" customClass="ArtistViewController" customModule="Persephone" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<view key="view" id="vxO-fC-BpZ">
|
<view key="view" id="vxO-fC-BpZ">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="450" height="300"/>
|
<rect key="frame" x="0.0" y="0.0" width="450" height="300"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
@ -896,9 +895,7 @@
|
|||||||
<collectionView id="8MP-vD-0zS">
|
<collectionView id="8MP-vD-0zS">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="450" height="158"/>
|
<rect key="frame" x="0.0" y="0.0" width="450" height="158"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
|
||||||
<collectionViewFlowLayout key="collectionViewLayout" minimumInteritemSpacing="10" minimumLineSpacing="10" id="0jX-3t-OLG">
|
<collectionViewLayout key="collectionViewLayout" id="Xgs-hh-JPN" customClass="ArtistViewLayout" customModule="Persephone" customModuleProvider="target"/>
|
||||||
<size key="itemSize" width="50" height="50"/>
|
|
||||||
</collectionViewFlowLayout>
|
|
||||||
<color key="primaryBackgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
<color key="primaryBackgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
</collectionView>
|
</collectionView>
|
||||||
</subviews>
|
</subviews>
|
||||||
@ -920,6 +917,9 @@
|
|||||||
<constraint firstAttribute="bottom" secondItem="Hef-8H-doh" secondAttribute="bottom" id="puR-GX-c6y"/>
|
<constraint firstAttribute="bottom" secondItem="Hef-8H-doh" secondAttribute="bottom" id="puR-GX-c6y"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
|
<connections>
|
||||||
|
<outlet property="artistCollectionView" destination="8MP-vD-0zS" id="Bb1-07-sRH"/>
|
||||||
|
</connections>
|
||||||
</viewController>
|
</viewController>
|
||||||
<customObject id="Ras-zf-6qF" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
<customObject id="Ras-zf-6qF" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
|
|||||||
14
Persephone/State/Actions/ArtistListActions.swift
Normal file
14
Persephone/State/Actions/ArtistListActions.swift
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// ArtistListActions.swift
|
||||||
|
// Persephone
|
||||||
|
//
|
||||||
|
// Created by Daniel Barber on 2019/9/29.
|
||||||
|
// Copyright © 2019 Dan Barber. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import AppKit
|
||||||
|
import ReSwift
|
||||||
|
|
||||||
|
struct UpdateArtistListAction: Action {
|
||||||
|
var artists: [String]
|
||||||
|
}
|
||||||
@ -12,6 +12,7 @@ struct AppState: StateType {
|
|||||||
var playerState = PlayerState()
|
var playerState = PlayerState()
|
||||||
var queueState = QueueState()
|
var queueState = QueueState()
|
||||||
var albumListState = AlbumListState()
|
var albumListState = AlbumListState()
|
||||||
|
var artistListState = ArtistListState()
|
||||||
var preferencesState = PreferencesState()
|
var preferencesState = PreferencesState()
|
||||||
var uiState = UIState()
|
var uiState = UIState()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ func appReducer(action: Action, state: AppState?) -> AppState {
|
|||||||
playerState: playerReducer(action: action, state: state?.playerState),
|
playerState: playerReducer(action: action, state: state?.playerState),
|
||||||
queueState: queueReducer(action: action, state: state?.queueState),
|
queueState: queueReducer(action: action, state: state?.queueState),
|
||||||
albumListState: albumListReducer(action: action, state: state?.albumListState),
|
albumListState: albumListReducer(action: action, state: state?.albumListState),
|
||||||
|
artistListState: artistListReducer(action: action, state: state?.artistListState),
|
||||||
preferencesState: preferencesReducer(action: action, state: state?.preferencesState),
|
preferencesState: preferencesReducer(action: action, state: state?.preferencesState),
|
||||||
uiState: uiReducer(action: action, state: state?.uiState)
|
uiState: uiReducer(action: action, state: state?.uiState)
|
||||||
)
|
)
|
||||||
|
|||||||
25
Persephone/State/Reducers/ArtistReducer.swift
Normal file
25
Persephone/State/Reducers/ArtistReducer.swift
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// ArtistReducer.swift
|
||||||
|
// Persephone
|
||||||
|
//
|
||||||
|
// Created by Daniel Barber on 2019/9/29.
|
||||||
|
// Copyright © 2019 Dan Barber. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import ReSwift
|
||||||
|
|
||||||
|
func artistListReducer(action: Action, state: ArtistListState?) -> ArtistListState {
|
||||||
|
var state = state ?? ArtistListState()
|
||||||
|
|
||||||
|
switch action {
|
||||||
|
case let action as UpdateArtistListAction:
|
||||||
|
state.artists = action.artists
|
||||||
|
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
15
Persephone/Views/ArtistItemView.swift
Normal file
15
Persephone/Views/ArtistItemView.swift
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// ArtistViewItem.swift
|
||||||
|
// Persephone
|
||||||
|
//
|
||||||
|
// Created by Daniel Barber on 2019/9/29.
|
||||||
|
// Copyright © 2019 Dan Barber. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import AppKit
|
||||||
|
|
||||||
|
class ArtistItemView: NSView {
|
||||||
|
required init?(coder decoder: NSCoder) {
|
||||||
|
super.init(coder: decoder)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user