Downloads fix, Spanish translation

This commit is contained in:
exttex 2020-09-22 19:13:54 +02:00
parent 2858859abd
commit 17df300a18
18 changed files with 548 additions and 103 deletions

View file

@ -123,7 +123,7 @@ class DeezerAPI {
Map<dynamic, dynamic> data = await callApi('deezer.pageAlbum', params: {
'alb_id': id,
'header': true,
'lang': 'us'
'lang': settings.deezerLanguage??'en'
});
return Album.fromPrivateJson(data['results']['DATA'], songsJson: data['results']['SONGS']);
}
@ -132,7 +132,7 @@ class DeezerAPI {
Future<Artist> artist(String id) async {
Map<dynamic, dynamic> data = await callApi('deezer.pageArtist', params: {
'art_id': id,
'lang': 'us',
'lang': settings.deezerLanguage??'en',
});
return Artist.fromPrivateJson(
data['results']['DATA'],
@ -145,7 +145,7 @@ class DeezerAPI {
Future<List<Track>> playlistTracksPage(String id, int start, {int nb = 50}) async {
Map data = await callApi('deezer.pagePlaylist', params: {
'playlist_id': id,
'lang': 'us',
'lang': settings.deezerLanguage??'en',
'nb': nb,
'tags': true,
'start': start
@ -157,7 +157,7 @@ class DeezerAPI {
Future<Playlist> playlist(String id, {int nb = 100}) async {
Map<dynamic, dynamic> data = await callApi('deezer.pagePlaylist', params: {
'playlist_id': id,
'lang': 'us',
'lang': settings.deezerLanguage??'en',
'nb': nb,
'tags': true,
'start': 0
@ -167,6 +167,10 @@ class DeezerAPI {
//Get playlist with all tracks
Future<Playlist> fullPlaylist(String id) async {
return await playlist(id, nb: 100000);
//OLD WORKAROUND
/*
Playlist p = await playlist(id, nb: 200);
for (int i=200; i<p.trackCount; i++) {
//Get another page of tracks
@ -176,6 +180,7 @@ class DeezerAPI {
continue;
}
return p;
*/
}
//Add track to favorites
@ -305,7 +310,7 @@ class DeezerAPI {
"large-card": ["album", "playlist", "show", "video-link"],
"ads": [] //Nope
},
"LANG": "us",
"LANG": settings.deezerLanguage??'en',
"OPTIONS": []
}));
return HomePage.fromPrivateJson(data['results']);
@ -336,7 +341,7 @@ class DeezerAPI {
"large-card": ["album", "playlist", "show", "video-link"],
"ads": [] //Nope
},
"LANG": "us",
"LANG": settings.deezerLanguage??'en',
"OPTIONS": []
}));
return HomePage.fromPrivateJson(data['results']);

View file

@ -186,10 +186,12 @@ class Album {
int fans;
bool offline; //If the album is offline, or just saved in db as metadata
bool library;
//TODO: Not in DB
AlbumType type;
String releaseDate;
Album({this.id, this.title, this.art, this.artists, this.tracks, this.fans, this.offline, this.library, this.type});
Album({this.id, this.title, this.art, this.artists, this.tracks, this.fans, this.offline, this.library, this.type, this.releaseDate});
String get artistString => artists.map<String>((art) => art.name).join(', ');
Duration get duration => Duration(seconds: tracks.fold(0, (v, t) => v += t.duration.inSeconds));
@ -210,7 +212,8 @@ class Album {
tracks: (songsJson['data']??[]).map<Track>((dynamic track) => Track.fromPrivateJson(track)).toList(),
fans: json['NB_FAN'],
library: library,
type: type
type: type,
releaseDate: json['DIGITAL_RELEASE_DATE']??json['PHYSICAL_RELEASE_DATE']
);
}
Map<String, dynamic> toSQL({off = false}) => {
@ -281,7 +284,7 @@ class Artist {
albums: (albumsJson['data']??[]).map<Album>((dynamic data) => Album.fromPrivateJson(data)).toList(),
topTracks: (topJson['data']??[]).map<Track>((dynamic data) => Track.fromPrivateJson(data)).toList(),
library: library,
radio: _radio
radio: _radio,
);
}
Map<String, dynamic> toSQL({off = false}) => {

View file

@ -70,6 +70,7 @@ Album _$AlbumFromJson(Map<String, dynamic> json) {
offline: json['offline'] as bool,
library: json['library'] as bool,
type: _$enumDecodeNullable(_$AlbumTypeEnumMap, json['type']),
releaseDate: json['releaseDate'] as String,
);
}
@ -83,6 +84,7 @@ Map<String, dynamic> _$AlbumToJson(Album instance) => <String, dynamic>{
'offline': instance.offline,
'library': instance.library,
'type': _$AlbumTypeEnumMap[instance.type],
'releaseDate': instance.releaseDate,
};
T _$enumDecode<T>(

View file

@ -132,10 +132,23 @@ class DownloadManager {
}
).catchError((e, st) async {
if (stopped) return;
print('Download error: $e\n$st');
//Catch download errors
_download = null;
_cancelNotifications = true;
//Deezer error - track is unavailable
if (queue[0].state == DownloadState.DEEZER_ERROR) {
await db.rawUpdate('UPDATE downloads SET state = 4 WHERE trackId = ?', [queue[0].track.id]);
queue.removeAt(0);
_cancelNotifications = false;
_download = null;
updateQueue();
return;
}
//Clean
_download = null;
stopped = true;
print('Download error: $e\n$st');
queue[0].state = DownloadState.NONE;
//Shift to end
queue.add(queue[0]);
@ -442,7 +455,7 @@ class DownloadManager {
Future<List<Download>> getFinishedDownloads() async {
//Fetch from db
List<Map> data = await db.rawQuery("SELECT * FROM downloads INNER JOIN tracks ON tracks.id = downloads.trackId WHERE downloads.state = 1");
List<Map> data = await db.rawQuery("SELECT * FROM downloads INNER JOIN tracks ON tracks.id = downloads.trackId WHERE downloads.state = 1 OR downloads.state > 3");
List<Download> downloads = data.map<Download>((d) => Download.fromSQL(d, parseTrack: true)).toList();
return downloads;
}
@ -545,6 +558,12 @@ class Download {
try {rawTrackPublic = await deezerAPI.callPublicApi('track/${this.track.id}');} catch (e) {rawTrackPublic = {};}
try {rawAlbumPublic = await deezerAPI.callPublicApi('album/${this.track.album.id}');} catch (e) {rawAlbumPublic = {};}
//Global block check
if (rawTrackPublic['available_countries'] != null && rawTrackPublic['available_countries'].length == 0) {
this.state = DownloadState.DEEZER_ERROR;
throw Exception('Download error - not on Deezer');
}
//Get path if public
RegExp sanitize = RegExp(r'[\/\\\?\%\*\:\|\"\<\>]');
//Download path
@ -608,6 +627,10 @@ class Download {
//Download
this.state = DownloadState.DOWNLOADING;
//Quality fallback
if (this.url == null)
await _fallback();
//Create download file
File downloadFile = File(this.path + '.ENC');
//Get start position
@ -616,26 +639,32 @@ class Download {
FileStat stat = await downloadFile.stat();
start = stat.size;
} else {
//Create file if doesnt exist
//Create file if doesn't exist
await downloadFile.create(recursive: true);
}
//Quality fallback
if (this.url == null)
await _fallback();
//Download
_cancel = CancelToken();
Response response = await dio.get(
this.url,
options: Options(
responseType: ResponseType.stream,
headers: {
'Range': 'bytes=$start-'
},
),
cancelToken: _cancel
);
Response response;
try {
response = await dio.get(
this.url,
options: Options(
responseType: ResponseType.stream,
headers: {
'Range': 'bytes=$start-'
},
),
cancelToken: _cancel
);
} on DioError catch (e) {
//Deezer fetch error
if (e.response.statusCode == 403 || e.response.statusCode == 404) {
this.state = DownloadState.DEEZER_ERROR;
}
throw Exception('Download error - Deezer blocked.');
}
//Size
this.total = int.parse(response.headers['Content-Length'][0]) + start;
this.received = start;
@ -655,7 +684,6 @@ class Download {
await _outSink.close();
_cancel = null;
this.state = DownloadState.POST;
//Decrypt
await platformChannel.invokeMethod('decryptTrack', {'id': track.id, 'path': path});
@ -754,21 +782,23 @@ class Download {
'trackId': track.id,
'path': path,
'url': url,
'state': state == DownloadState.DONE ? 1:0,
'state': state.index,
'private': private?1:0
};
factory Download.fromSQL(Map<String, dynamic> data, {parseTrack = false}) => Download(
track: parseTrack?Track.fromSQL(data):Track(id: data['trackId']),
path: data['path'],
url: data['url'],
state: data['state'] == 1 ? DownloadState.DONE:DownloadState.NONE,
state: DownloadState.values[data['state']],
private: data['private'] == 1
);
}
enum DownloadState {
NONE,
DONE,
DOWNLOADING,
POST,
DONE
DEEZER_ERROR,
ERROR
}

View file

@ -485,7 +485,9 @@ class AudioPlayerTask extends BackgroundAudioTask {
//Load queue after some initialization in frontend
if (name == 'load') await this._loadQueueFile();
//Shuffle
if (name == 'shuffle') await _player.setShuffleModeEnabled(args);
if (name == 'shuffle') {
await _player.setShuffleModeEnabled(args);
}
//Android auto callback
if (name == 'screenAndroidAuto' && _androidAutoCallback != null) {
_androidAutoCallback.complete(jsonDecode(args).map<MediaItem>((m) => MediaItem.fromJson(m)).toList());