diff --git a/lib/api/deezer.dart b/lib/api/deezer.dart index bbfd674..78d48e8 100644 --- a/lib/api/deezer.dart +++ b/lib/api/deezer.dart @@ -439,5 +439,13 @@ class DeezerAPI { }); return data['results']['data'].map((t) => Track.fromPrivateJson(t)).toList(); } + + // Get similar tracks for track with id [trackId] + Future> playMix(String trackId) async { + Map data = await callApi('song.getContextualTrackMix', params: { + 'sng_ids': [trackId] + }); + return data['results']['data'].map((t) => Track.fromPrivateJson(t)).toList(); + } } diff --git a/lib/api/player.dart b/lib/api/player.dart index 6c73d26..577639a 100644 --- a/lib/api/player.dart +++ b/lib/api/player.dart @@ -150,33 +150,30 @@ class PlayerHelper { //Flow if (queueSource == null) return; - if (queueSource.id == 'flow') { - List tracks = await deezerAPI.flow(); - List mi = tracks.map((t) => t.toMediaItem()).toList(); - await AudioService.addQueueItems(mi); - AudioService.skipToNext(); - return; + List tracks = []; + switch(queueSource.source) { + case 'flow': + tracks = await deezerAPI.flow(); + break; + case 'smartradio': //SmartRadio/Artist radio + tracks = await deezerAPI.smartRadio(queueSource.id); + break; + case 'libraryshuffle': //Library shuffle + tracks = await deezerAPI.libraryShuffle(start: AudioService.queue.length); + break; + case 'mix': + tracks = await deezerAPI.playMix(queueSource.id); + // Deduplicate tracks with the same id + List queueIds = AudioService.queue.map((e) => e.id).toList(); + tracks.removeWhere((track) => queueIds.contains(track.id)); + break; + default: + print(queueSource.toJson()); } - //SmartRadio/Artist radio - if (queueSource.source == 'smartradio') { - List tracks = await deezerAPI.smartRadio(queueSource.id); - List mi = tracks.map((t) => t.toMediaItem()).toList(); - await AudioService.addQueueItems(mi); - AudioService.skipToNext(); - return; - } - - //Library shuffle - if (queueSource.source == 'libraryshuffle') { - List tracks = await deezerAPI.libraryShuffle(start: AudioService.queue.length); - List mi = tracks.map((t) => t.toMediaItem()).toList(); - await AudioService.addQueueItems(mi); - AudioService.skipToNext(); - return; - } - - print(queueSource.toJson()); + List mi = tracks.map((t) => t.toMediaItem()).toList(); + await AudioService.addQueueItems(mi); + AudioService.skipToNext(); } //Play track from album @@ -187,6 +184,16 @@ class PlayerHelper { source: 'album' )); } + + //Play mix by track + Future playMix(String trackId, String trackTitle) async { + List tracks = await deezerAPI.playMix(trackId); + playFromTrackList(tracks, tracks[0].id, QueueSource( + id: trackId, + text: 'Mix based on'.i18n + ' $trackTitle', + source: 'mix' + )); + } //Play from artist top tracks Future playFromTopTracks(List tracks, String trackId, Artist artist) async { await playFromTrackList(tracks, trackId, QueueSource( diff --git a/lib/ui/menu.dart b/lib/ui/menu.dart index 805ac8b..cb29ba4 100644 --- a/lib/ui/menu.dart +++ b/lib/ui/menu.dart @@ -7,6 +7,7 @@ import 'package:fluttertoast/fluttertoast.dart'; import 'package:freezer/api/cache.dart'; import 'package:freezer/api/deezer.dart'; import 'package:freezer/api/download.dart'; +import 'package:freezer/api/player.dart'; import 'package:freezer/ui/details_screens.dart'; import 'package:freezer/ui/error.dart'; import 'package:freezer/translations.i18n.dart'; @@ -132,6 +133,7 @@ class MenuSheet { addToPlaylist(track), downloadTrack(track), shareTile('track', track.id), + playMix(track), showAlbum(track.album), ...List.generate(track.artists.length, (i) => showArtist(track.artists[i])), ...options @@ -289,6 +291,14 @@ class MenuSheet { }, ); + Widget playMix(Track track) => ListTile( + title: Text('Play mix'.i18n), + leading: Icon(Icons.online_prediction), + onTap: () async { + playerHelper.playMix(track.id, track.title); + _close(); + }, + ); //=================== // ALBUM