Skip to content

Commit

Permalink
Songs: request random songs from server
Browse files Browse the repository at this point in the history
  • Loading branch information
BLeeEZ committed Aug 4, 2021
1 parent 52f2751 commit 232e6b5
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 2 deletions.
8 changes: 8 additions & 0 deletions Amperfy/Api/Ampache/AmpacheLibrarySyncer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ class AmpacheLibrarySyncer: LibrarySyncer {
func sync(directory: Directory, library: LibraryStorage) {
ampacheXmlServerApi.eventLogger.error(topic: "Internal Error", statusCode: .internalError, message: "GetMusicDirectory API function is not support by Ampache")
}

func requestRandomSongs(playlist: Playlist, count: Int, library: LibraryStorage) {
guard let syncWave = library.getLatestSyncWave() else { return }
let parser = SongParserDelegate(library: library, syncWave: syncWave, parseNotifier: nil)
ampacheXmlServerApi.requestRandomSongs(parserDelegate: parser, count: count)
playlist.append(playables: parser.parsedSongs)
library.saveContext()
}

func syncDownPlaylistsWithoutSongs(library: LibraryStorage) {
let playlistParser = PlaylistParserDelegate(library: library, parseNotifier: nil)
Expand Down
11 changes: 10 additions & 1 deletion Amperfy/Api/Ampache/AmpacheXmlServerApi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class AmpacheXmlServerApi {
url.appendPathComponent("image.php")
guard var urlComp = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return "" }
urlComp.addQueryItem(name: "object_id", value: "0")
urlComp.addQueryItem(name: "object_type", value: "album")
urlComp.addQueryItem(name: "object_type", value: "artist")
urlComp.addQueryItem(name: "auth", value: auth.token)
guard let urlString = urlComp.string else { return ""}
return urlString
Expand Down Expand Up @@ -296,6 +296,15 @@ class AmpacheXmlServerApi {
request(fromUrlComponent: apiUrlComponent, viaXmlParser: parserDelegate)
}

func requestRandomSongs(parserDelegate: AmpacheXmlParser, count: Int) {
guard var apiUrlComponent = createAuthenticatedApiUrlComponent() else { return }
apiUrlComponent.addQueryItem(name: "action", value: "playlist_generate")
apiUrlComponent.addQueryItem(name: "mode", value: "random")
apiUrlComponent.addQueryItem(name: "format", value: "song")
apiUrlComponent.addQueryItem(name: "limit", value: count)
request(fromUrlComponent: apiUrlComponent, viaXmlParser: parserDelegate)
}

func requestPlaylists(parserDelegate: AmpacheXmlParser) {
guard var apiUrlComponent = createAuthenticatedApiUrlComponent() else { return }
apiUrlComponent.addQueryItem(name: "action", value: "playlists")
Expand Down
4 changes: 4 additions & 0 deletions Amperfy/Api/Ampache/SongParserDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import os.log
class SongParserDelegate: PlayableParserDelegate {

var songBuffer: Song?
var parsedSongs = [Song]()
var artistIdToCreate: String?
var albumIdToCreate: String?
var genreIdToCreate: String?
Expand Down Expand Up @@ -89,6 +90,9 @@ class SongParserDelegate: PlayableParserDelegate {
parsedCount += 1
parseNotifier?.notifyParsedObject(ofType: .song)
playableBuffer = nil
if let song = songBuffer {
parsedSongs.append(song)
}
songBuffer = nil
default:
break
Expand Down
1 change: 1 addition & 0 deletions Amperfy/Api/BackendApi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ protocol LibrarySyncer {
func syncMusicFolders(library: LibraryStorage)
func syncIndexes(musicFolder: MusicFolder, library: LibraryStorage)
func sync(directory: Directory, library: LibraryStorage)
func requestRandomSongs(playlist: Playlist, count: Int, library: LibraryStorage)
}

protocol AbstractBackgroundLibrarySyncer {
Expand Down
4 changes: 4 additions & 0 deletions Amperfy/Api/Subsonic/SsSongParserDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import os.log
class SsSongParserDelegate: SsPlayableParserDelegate {

var songBuffer: Song?
var parsedSongs = [Song]()
var guessedArtist: Artist?
var guessedAlbum: Album?
var guessedGenre: Genre?
Expand Down Expand Up @@ -76,6 +77,9 @@ class SsSongParserDelegate: SsPlayableParserDelegate {
if elementName == "song" || elementName == "entry" || elementName == "child" || elementName == "episode", songBuffer != nil {
parsedCount += 1
playableBuffer = nil
if let song = songBuffer {
parsedSongs.append(song)
}
songBuffer = nil
}

Expand Down
8 changes: 8 additions & 0 deletions Amperfy/Api/Subsonic/SubsonicLibrarySyncer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ class SubsonicLibrarySyncer: LibrarySyncer {
library.saveContext()
}

func requestRandomSongs(playlist: Playlist, count: Int, library: LibraryStorage) {
guard let syncWave = library.getLatestSyncWave() else { return }
let songParser = SsSongParserDelegate(library: library, syncWave: syncWave, subsonicUrlCreator: subsonicServerApi)
subsonicServerApi.requestRandomSongs(parserDelegate: songParser, count: count)
playlist.append(playables: songParser.parsedSongs)
library.saveContext()
}

func syncDownPlaylistsWithoutSongs(library: LibraryStorage) {
let playlistParser = SsPlaylistParserDelegate(library: library)
subsonicServerApi.requestPlaylists(parserDelegate: playlistParser)
Expand Down
6 changes: 6 additions & 0 deletions Amperfy/Api/Subsonic/SubsonicServerApi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,12 @@ class SubsonicServerApi {
request(fromUrlComponent: urlComp, viaXmlParser: parserDelegate)
}

func requestRandomSongs(parserDelegate: SsXmlParser, count: Int) {
guard var urlComp = createAuthenticatedApiUrlComponent(forAction: "getRandomSongs") else { return }
urlComp.addQueryItem(name: "size", value: count)
request(fromUrlComponent: urlComp, viaXmlParser: parserDelegate)
}

func requestSearchArtists(parserDelegate: SsXmlParser, searchText: String) {
guard var urlComp = createAuthenticatedApiUrlComponent(forAction: "search3") else { return }
urlComp.addQueryItem(name: "query", value: searchText)
Expand Down
2 changes: 1 addition & 1 deletion Amperfy/Screens/ViewController/DownloadsVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class DownloadsVC: SingleFetchedResultsTableViewController<DownloadMO> {
tableView.register(nibName: PlayableTableCell.typeName)
tableView.rowHeight = PlayableTableCell.rowHeight

actionButton = UIBarButtonItem(title: "...", style: .plain, target: self, action: #selector(performActionButtonOperation))
actionButton = UIBarButtonItem(title: "\(CommonString.threeMiddleDots)", style: .plain, target: self, action: #selector(performActionButtonOperation))
navigationItem.rightBarButtonItem = actionButton
}

Expand Down
29 changes: 29 additions & 0 deletions Amperfy/Screens/ViewController/SongsVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import CoreData
class SongsVC: SingleFetchedResultsTableViewController<SongMO> {

private var fetchedResultsController: SongFetchedResultsController!
private var optionsButton: UIBarButtonItem!

override func viewDidLoad() {
super.viewDidLoad()
Expand All @@ -15,6 +16,9 @@ class SongsVC: SingleFetchedResultsTableViewController<SongMO> {
configureSearchController(placeholder: "Search in \"Songs\"", scopeButtonTitles: ["All", "Cached"], showSearchBarAtEnter: false)
tableView.register(nibName: SongTableCell.typeName)
tableView.rowHeight = SongTableCell.rowHeight

optionsButton = UIBarButtonItem(title: "\(CommonString.threeMiddleDots)", style: .plain, target: self, action: #selector(optionsPressed))
navigationItem.rightBarButtonItem = optionsButton
}

override func viewWillAppear(_ animated: Bool) {
Expand Down Expand Up @@ -45,5 +49,30 @@ class SongsVC: SingleFetchedResultsTableViewController<SongMO> {
tableView.reloadData()
}

@objc private func optionsPressed() {
let alert = UIAlertController(title: "Songs", message: nil, preferredStyle: .actionSheet)

alert.addAction(UIAlertAction(title: "Play random songs", style: .default, handler: { _ in
self.appDelegate.persistentStorage.persistentContainer.performBackgroundTask() { (context) in
let syncLibrary = LibraryStorage(context: context)
let syncer = self.appDelegate.backendApi.createLibrarySyncer()
let randomSongsPlaylist = syncLibrary.createPlaylist()
syncer.requestRandomSongs(playlist: randomSongsPlaylist, count: 100, library: syncLibrary)
DispatchQueue.main.async {
let playlistMain = randomSongsPlaylist.getManagedObject(in: self.appDelegate.persistentStorage.context, library: self.appDelegate.library)
self.appDelegate.player.cleanPlaylist()
self.appDelegate.player.addToPlaylist(playables: playlistMain.playables)
self.appDelegate.player.play()
self.appDelegate.library.deletePlaylist(playlistMain)
self.appDelegate.library.saveContext()
}
}
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
alert.pruneNegativeWidthConstraintsToAvoidFalseConstraintWarnings()
alert.setOptionsForIPadToDisplayPopupCentricIn(view: self.view)
present(alert, animated: true, completion: nil)
}

}

1 change: 1 addition & 0 deletions AmperfyTests/Cases/Player/MusicPlayerTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class MOCK_LibrarySyncer: LibrarySyncer {
func syncMusicFolders(library: LibraryStorage) {}
func syncIndexes(musicFolder: MusicFolder, library: LibraryStorage) {}
func sync(directory: Directory, library: LibraryStorage) {}
func requestRandomSongs(playlist: Playlist, count: Int, library: LibraryStorage) {}
}

class MOCK_BackgroundLibrarySyncer: BackgroundLibrarySyncer {
Expand Down

0 comments on commit 232e6b5

Please sign in to comment.