Compare commits

..

1 Commits

Author SHA1 Message Date
Guanciottaman
8aa4681ba5
Merge ff252d6b14 into ca6924f5a9 2025-09-18 23:44:59 +06:00
46 changed files with 65 additions and 476 deletions

View File

@ -39,11 +39,6 @@ class InstallDependenciesCommand extends Command {
switch (argResults!.option("platform")) { switch (argResults!.option("platform")) {
case "windows": case "windows":
await shell.run(
"""
choco install innosetup -y
""",
);
break; break;
case "linux": case "linux":
await shell.run( await shell.run(

View File

@ -462,6 +462,5 @@
"configure_your_own_metadata_plugin": "Configure your own playlist/album/artist/feed metadata provider", "configure_your_own_metadata_plugin": "Configure your own playlist/album/artist/feed metadata provider",
"audio_scrobblers": "Audio Scrobblers", "audio_scrobblers": "Audio Scrobblers",
"scrobbling": "Scrobbling", "scrobbling": "Scrobbling",
"source": "Source: ", "source": "Source: "
"uncompressed": "Uncompressed"
} }

View File

@ -2936,12 +2936,6 @@ abstract class AppLocalizations {
/// In en, this message translates to: /// In en, this message translates to:
/// **'Source: '** /// **'Source: '**
String get source; String get source;
/// No description provided for @uncompressed.
///
/// In en, this message translates to:
/// **'Uncompressed'**
String get uncompressed;
} }
class _AppLocalizationsDelegate class _AppLocalizationsDelegate

View File

@ -1540,7 +1540,4 @@ class AppLocalizationsAr extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1541,7 +1541,4 @@ class AppLocalizationsBn extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1551,7 +1551,4 @@ class AppLocalizationsCa extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1541,7 +1541,4 @@ class AppLocalizationsCs extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1553,7 +1553,4 @@ class AppLocalizationsDe extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1539,7 +1539,4 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1554,7 +1554,4 @@ class AppLocalizationsEs extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1551,7 +1551,4 @@ class AppLocalizationsEu extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1539,7 +1539,4 @@ class AppLocalizationsFa extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1539,7 +1539,4 @@ class AppLocalizationsFi extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1559,7 +1559,4 @@ class AppLocalizationsFr extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1545,7 +1545,4 @@ class AppLocalizationsHi extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1547,7 +1547,4 @@ class AppLocalizationsId extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1546,7 +1546,4 @@ class AppLocalizationsIt extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1510,7 +1510,4 @@ class AppLocalizationsJa extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1548,7 +1548,4 @@ class AppLocalizationsKa extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1514,7 +1514,4 @@ class AppLocalizationsKo extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1551,7 +1551,4 @@ class AppLocalizationsNe extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1545,7 +1545,4 @@ class AppLocalizationsNl extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1547,7 +1547,4 @@ class AppLocalizationsPl extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1544,7 +1544,4 @@ class AppLocalizationsPt extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1547,7 +1547,4 @@ class AppLocalizationsRu extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1553,7 +1553,4 @@ class AppLocalizationsTa extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1536,7 +1536,4 @@ class AppLocalizationsTh extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1554,7 +1554,4 @@ class AppLocalizationsTl extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1547,7 +1547,4 @@ class AppLocalizationsTr extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1543,7 +1543,4 @@ class AppLocalizationsUk extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1549,7 +1549,4 @@ class AppLocalizationsVi extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }

View File

@ -1503,9 +1503,6 @@ class AppLocalizationsZh extends AppLocalizations {
@override @override
String get source => 'Source: '; String get source => 'Source: ';
@override
String get uncompressed => 'Uncompressed';
} }
/// The translations for Chinese, as used in Taiwan (`zh_TW`). /// The translations for Chinese, as used in Taiwan (`zh_TW`).

View File

@ -12,14 +12,12 @@ enum CloseBehavior {
} }
enum AudioSource { enum AudioSource {
youtube("YouTube"), youtube,
piped("Piped"), piped,
jiosaavn("JioSaavn"), jiosaavn,
invidious("Invidious"), invidious;
dabMusic("DAB Music");
final String label; String get label => name[0].toUpperCase() + name.substring(1);
const AudioSource(this.label);
} }
enum YoutubeClientEngine { enum YoutubeClientEngine {
@ -41,6 +39,14 @@ enum YoutubeClientEngine {
} }
} }
enum MusicCodec {
m4a._("M4a (Best for downloaded music)"),
weba._("WebA (Best for streamed music)\nDoesn't support audio metadata");
final String label;
const MusicCodec._(this.label);
}
enum SearchMode { enum SearchMode {
youtube._("YouTube"), youtube._("YouTube"),
youtubeMusic._("YouTube Music"); youtubeMusic._("YouTube Music");

View File

@ -3,8 +3,7 @@ part of '../database.dart';
enum SourceType { enum SourceType {
youtube._("YouTube"), youtube._("YouTube"),
youtubeMusic._("YouTube Music"), youtubeMusic._("YouTube Music"),
jiosaavn._("JioSaavn"), jiosaavn._("JioSaavn");
dabMusic._("DAB Music");
final String label; final String label;

View File

@ -8,7 +8,7 @@ import 'package:flutter/material.dart' show ListTile;
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:piped_client/piped_client.dart'; import 'package:piped_client/piped_client.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer;
import 'package:spotube/collections/routes.gr.dart'; import 'package:spotube/collections/routes.gr.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/models/database/database.dart'; import 'package:spotube/models/database/database.dart';
@ -44,11 +44,6 @@ class SettingsPlaybackSection extends HookConsumerWidget {
title: Text(context.l10n.audio_quality), title: Text(context.l10n.audio_quality),
value: preferences.audioQuality, value: preferences.audioQuality,
options: [ options: [
if (preferences.audioSource == AudioSource.dabMusic)
SelectItemButton(
value: SourceQualities.uncompressed,
child: Text(context.l10n.uncompressed),
),
SelectItemButton( SelectItemButton(
value: SourceQualities.high, value: SourceQualities.high,
child: Text(context.l10n.high), child: Text(context.l10n.high),
@ -401,9 +396,7 @@ class SettingsPlaybackSection extends HookConsumerWidget {
onChanged: preferencesNotifier.setNormalizeAudio, onChanged: preferencesNotifier.setNormalizeAudio,
), ),
), ),
if (const [AudioSource.jiosaavn, AudioSource.dabMusic] if (preferences.audioSource != AudioSource.jiosaavn) ...[
.contains(preferences.audioSource) ==
false) ...[
AdaptiveSelectTile<SourceCodecs>( AdaptiveSelectTile<SourceCodecs>(
popupConstraints: const BoxConstraints(maxWidth: 300), popupConstraints: const BoxConstraints(maxWidth: 300),
secondary: const Icon(SpotubeIcons.stream), secondary: const Icon(SpotubeIcons.stream),

View File

@ -101,7 +101,10 @@ class ServerPlaybackRoutes {
); );
final contentLengthRes = await Future<dio_lib.Response?>.value( final contentLengthRes = await Future<dio_lib.Response?>.value(
dio.head(url, options: options), dio.head(
url,
options: options,
),
).catchError((e, stack) async { ).catchError((e, stack) async {
AppLogger.reportError(e, stack); AppLogger.reportError(e, stack);
@ -132,17 +135,19 @@ class ServerPlaybackRoutes {
); );
} }
if (headers["range"] == "bytes=0-") { final contentLength = contentLengthRes?.headers.value("content-length");
final bufferSize =
userPreferences.audioQuality == SourceQualities.uncompressed /// Forcing partial content range as mpv sometimes greedily wants
? 6 * 1024 * 1024 /// everything at one go. Slows down overall streaming.
: 4 * 1024 * 1024; final range = RangeHeader.parse(headers["range"] ?? "");
final endRange = min(bufferSize, final contentPartialLength = int.tryParse(contentLength ?? "");
int.parse(contentLengthRes?.headers.value("content-length") ?? "0")); if ((range.end == null) &&
contentPartialLength != null &&
range.start == 0) {
options = options.copyWith( options = options.copyWith(
headers: { headers: {
...options.headers ?? {}, ...?options.headers,
"range": "bytes=0-$endRange", "range": "$range${(contentPartialLength * 0.3).ceil()}",
}, },
); );
} }

View File

@ -54,7 +54,6 @@ class UserPreferencesNotifier extends Notifier<PreferencesTableData> {
} }
await audioPlayer.setAudioNormalization(state.normalizeAudio); await audioPlayer.setAudioNormalization(state.normalizeAudio);
await _updatePlayerBufferSize(event.audioQuality, state.audioQuality);
} catch (e, stack) { } catch (e, stack) {
AppLogger.reportError(e, stack); AppLogger.reportError(e, stack);
} }
@ -80,24 +79,6 @@ class UserPreferencesNotifier extends Notifier<PreferencesTableData> {
}); });
} }
/// Sets audio player's buffer size based on the selected audio quality
/// Uncompressed quality gets a larger buffer size for smoother playback
/// while other qualities use a standard buffer size.
Future<void> _updatePlayerBufferSize(
SourceQualities newQuality,
SourceQualities oldQuality,
) async {
if (newQuality == SourceQualities.uncompressed) {
audioPlayer.setDemuxerBufferSize(6 * 1024 * 1024); // 6MB
return;
}
if (oldQuality == SourceQualities.uncompressed &&
newQuality != SourceQualities.uncompressed) {
audioPlayer.setDemuxerBufferSize(4 * 1024 * 1024); // 4MB
}
}
Future<void> setData(PreferencesTableCompanion data) async { Future<void> setData(PreferencesTableCompanion data) async {
final db = ref.read(databaseProvider); final db = ref.read(databaseProvider);
@ -174,7 +155,6 @@ class UserPreferencesNotifier extends Notifier<PreferencesTableData> {
void setAudioQuality(SourceQualities quality) { void setAudioQuality(SourceQualities quality) {
setData(PreferencesTableCompanion(audioQuality: Value(quality))); setData(PreferencesTableCompanion(audioQuality: Value(quality)));
_updatePlayerBufferSize(quality, state.audioQuality);
} }
void setDownloadLocation(String downloadDir) { void setDownloadLocation(String downloadDir) {
@ -224,11 +204,6 @@ class UserPreferencesNotifier extends Notifier<PreferencesTableData> {
} }
void setAudioSource(AudioSource type) { void setAudioSource(AudioSource type) {
// Only allow uncompressed quality for DAB Music
if (type != AudioSource.dabMusic &&
state.audioQuality == SourceQualities.uncompressed) {
setAudioQuality(SourceQualities.high);
}
setData(PreferencesTableCompanion(audioSource: Value(type))); setData(PreferencesTableCompanion(audioSource: Value(type)));
} }

View File

@ -56,7 +56,6 @@ abstract class AudioPlayerInterface {
configuration: const mk.PlayerConfiguration( configuration: const mk.PlayerConfiguration(
title: "Spotube", title: "Spotube",
logLevel: kDebugMode ? mk.MPVLogLevel.info : mk.MPVLogLevel.error, logLevel: kDebugMode ? mk.MPVLogLevel.info : mk.MPVLogLevel.error,
bufferSize: 4 * 1024 * 1024, // 4MB buffer
), ),
) { ) {
_mkPlayer.stream.error.listen((event) { _mkPlayer.stream.error.listen((event) {

View File

@ -131,8 +131,4 @@ class SpotubeAudioPlayer extends AudioPlayerInterface
Future<void> setAudioNormalization(bool normalize) async { Future<void> setAudioNormalization(bool normalize) async {
await _mkPlayer.setAudioNormalization(normalize); await _mkPlayer.setAudioNormalization(normalize);
} }
Future<void> setDemuxerBufferSize(int sizeInBytes) async {
await _mkPlayer.setDemuxerBufferSize(sizeInBytes);
}
} }

View File

@ -133,12 +133,4 @@ class CustomPlayer extends Player {
await nativePlayer.setProperty('af', ''); await nativePlayer.setProperty('af', '');
} }
} }
Future<void> setDemuxerBufferSize(int sizeInBytes) async {
await nativePlayer.setProperty('demuxer-max-bytes', sizeInBytes.toString());
await nativePlayer.setProperty(
'demuxer-max-back-bytes',
sizeInBytes.toString(),
);
}
} }

View File

@ -2,16 +2,13 @@ import 'package:spotube/models/playback/track_sources.dart';
enum SourceCodecs { enum SourceCodecs {
m4a._("M4a (Best for downloaded music)"), m4a._("M4a (Best for downloaded music)"),
weba._("WebA (Best for streamed music)\nDoesn't support audio metadata"), weba._("WebA (Best for streamed music)\nDoesn't support audio metadata");
mp3._("MP3 (Widely supported audio format)"),
flac._("FLAC (Lossless, best quality)\nLarge file size");
final String label; final String label;
const SourceCodecs._(this.label); const SourceCodecs._(this.label);
} }
enum SourceQualities { enum SourceQualities {
uncompressed(3),
high(2), high(2),
medium(1), medium(1),
low(0); low(0);

View File

@ -5,7 +5,6 @@ import 'package:spotube/models/playback/track_sources.dart';
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
import 'package:spotube/services/sourced_track/enums.dart'; import 'package:spotube/services/sourced_track/enums.dart';
import 'package:spotube/services/sourced_track/sources/dab_music.dart';
import 'package:spotube/services/sourced_track/sources/invidious.dart'; import 'package:spotube/services/sourced_track/sources/invidious.dart';
import 'package:spotube/services/sourced_track/sources/jiosaavn.dart'; import 'package:spotube/services/sourced_track/sources/jiosaavn.dart';
import 'package:spotube/services/sourced_track/sources/piped.dart'; import 'package:spotube/services/sourced_track/sources/piped.dart';
@ -75,14 +74,6 @@ abstract class SourcedTrack extends BasicSourcedTrack {
query: query, query: query,
sources: sources, sources: sources,
), ),
AudioSource.dabMusic => DABMusicSourcedTrack(
ref: ref,
source: source,
siblings: siblings,
info: info,
query: query,
sources: sources,
),
}; };
} }
@ -113,8 +104,6 @@ abstract class SourcedTrack extends BasicSourcedTrack {
await InvidiousSourcedTrack.fetchFromTrack(query: query, ref: ref), await InvidiousSourcedTrack.fetchFromTrack(query: query, ref: ref),
AudioSource.jiosaavn => AudioSource.jiosaavn =>
await JioSaavnSourcedTrack.fetchFromTrack(query: query, ref: ref), await JioSaavnSourcedTrack.fetchFromTrack(query: query, ref: ref),
AudioSource.dabMusic =>
await DABMusicSourcedTrack.fetchFromTrack(query: query, ref: ref),
}; };
} catch (e) { } catch (e) {
if (preferences.audioSource == AudioSource.youtube) { if (preferences.audioSource == AudioSource.youtube) {
@ -140,8 +129,6 @@ abstract class SourcedTrack extends BasicSourcedTrack {
JioSaavnSourcedTrack.fetchSiblings(query: query, ref: ref), JioSaavnSourcedTrack.fetchSiblings(query: query, ref: ref),
AudioSource.invidious => AudioSource.invidious =>
InvidiousSourcedTrack.fetchSiblings(query: query, ref: ref), InvidiousSourcedTrack.fetchSiblings(query: query, ref: ref),
AudioSource.dabMusic =>
DABMusicSourcedTrack.fetchSiblings(query: query, ref: ref),
}; };
} }
@ -211,14 +198,9 @@ abstract class SourcedTrack extends BasicSourcedTrack {
SourceCodecs get codec { SourceCodecs get codec {
final preferences = ref.read(userPreferencesProvider); final preferences = ref.read(userPreferencesProvider);
return switch (preferences.audioSource) { return preferences.audioSource == AudioSource.jiosaavn
AudioSource.dabMusic => ? SourceCodecs.m4a
preferences.audioQuality == SourceQualities.uncompressed : preferences.streamMusicCodec;
? SourceCodecs.flac
: SourceCodecs.mp3,
AudioSource.jiosaavn => SourceCodecs.m4a,
_ => preferences.streamMusicCodec
};
} }
TrackSource get activeTrackSource { TrackSource get activeTrackSource {

View File

@ -1,206 +0,0 @@
import 'package:collection/collection.dart';
import 'package:dio/dio.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:spotube/models/database/database.dart';
import 'package:spotube/models/playback/track_sources.dart';
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
import 'package:spotube/services/logger/logger.dart';
import 'package:spotube/services/sourced_track/enums.dart';
import 'package:spotube/services/sourced_track/exceptions.dart';
import 'package:spotube/services/sourced_track/sourced_track.dart';
import 'package:dab_music_api/dab_music_api.dart';
final dabMusicApiClient = DabMusicApiClient(
Dio(),
baseUrl: "https://dab.yeet.su/api",
);
/// Only Music source that can't support database caching due to having no endpoint.
/// But ISRC search is 100% reliable so caching is actually not necessary.
class DABMusicSourcedTrack extends SourcedTrack {
DABMusicSourcedTrack({
required super.ref,
required super.source,
required super.siblings,
required super.info,
required super.query,
required super.sources,
});
static Future<SourcedTrack> fetchFromTrack({
required TrackSourceQuery query,
required Ref ref,
}) async {
try {
final siblings = await fetchSiblings(ref: ref, query: query);
if (siblings.isEmpty) {
throw TrackNotFoundError(query);
}
return DABMusicSourcedTrack(
ref: ref,
siblings: siblings.map((s) => s.info).skip(1).toList(),
sources: siblings.first.source!,
info: siblings.first.info,
query: query,
source: AudioSource.dabMusic,
);
} catch (e, stackTrace) {
AppLogger.reportError(e, stackTrace);
rethrow;
}
}
static Future<List<TrackSource>> fetchSources(
String id,
SourceQualities quality,
) async {
try {
final isUncompressed = quality == SourceQualities.uncompressed;
final streamResponse = await dabMusicApiClient.music.getStream(
trackId: id,
quality: isUncompressed ? "27" : "5",
);
if (streamResponse.url == null) {
throw Exception("No stream URL found for track ID: $id");
}
return [
TrackSource(
url: streamResponse.url!,
quality: isUncompressed
? SourceQualities.uncompressed
: SourceQualities.high,
bitrate: isUncompressed ? "2998kbps" : "320kbps",
codec: isUncompressed ? SourceCodecs.flac : SourceCodecs.mp3,
),
];
} catch (e, stackTrace) {
AppLogger.reportError(e, stackTrace);
rethrow;
}
}
static Future<SiblingType> toSiblingType(
Ref ref,
int index,
Track result,
) async {
try {
List<TrackSource>? source;
if (index == 0) {
source = await fetchSources(
result.id.toString(),
ref.read(userPreferencesProvider).audioQuality,
);
}
final SiblingType sibling = (
info: TrackSourceInfo(
artists: result.artist!,
durationMs: Duration(seconds: result.duration!).inMilliseconds,
id: result.id.toString(),
pageUrl: "https://dab.yeet.su/music/${result.id}",
thumbnail: result.albumCover!,
title: result.title!,
),
source: source,
);
return sibling;
} catch (e, stackTrace) {
AppLogger.reportError(e, stackTrace);
rethrow;
}
}
static Future<List<SiblingType>> fetchSiblings({
required TrackSourceQuery query,
required Ref ref,
}) async {
try {
List<Track> results = [];
if (query.isrc.isNotEmpty) {
final res =
await dabMusicApiClient.music.getSearch(q: query.isrc, limit: 1);
results = res.tracks ?? <Track>[];
}
if (results.isEmpty) {
final res = await dabMusicApiClient.music.getSearch(
q: SourcedTrack.getSearchTerm(query),
limit: 5,
);
results = res.tracks ?? <Track>[];
}
if (results.isEmpty) {
return [];
}
final matchedResults =
results.mapIndexed((index, d) => toSiblingType(ref, index, d));
return Future.wait(matchedResults);
} catch (e, stackTrace) {
AppLogger.reportError(e, stackTrace);
rethrow;
}
}
@override
Future<DABMusicSourcedTrack> copyWithSibling() async {
if (siblings.isNotEmpty) {
return this;
}
final fetchedSiblings = await fetchSiblings(ref: ref, query: query);
return DABMusicSourcedTrack(
ref: ref,
siblings: fetchedSiblings
.where((s) => s.info.id != info.id)
.map((s) => s.info)
.toList(),
source: source,
info: info,
query: query,
sources: sources,
);
}
@override
Future<DABMusicSourcedTrack?> swapWithSibling(TrackSourceInfo sibling) async {
if (sibling.id == this.info.id) {
return null;
}
// a sibling source that was fetched from the search results
final isStepSibling = siblings.none((s) => s.id == sibling.id);
final newSourceInfo = isStepSibling
? sibling
: siblings.firstWhere((s) => s.id == sibling.id);
final newSiblings = siblings.where((s) => s.id != sibling.id).toList()
..insert(0, this.info);
final source = await fetchSources(
sibling.id,
ref.read(userPreferencesProvider).audioQuality,
);
return DABMusicSourcedTrack(
ref: ref,
siblings: newSiblings,
sources: source,
info: newSourceInfo,
query: query,
source: AudioSource.dabMusic,
);
}
@override
Future<SourcedTrack> refreshStream() async {
// There's no need to refresh the stream for DABMusicSourcedTrack
return this;
}
}

View File

@ -458,15 +458,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.2" version: "1.0.2"
dab_music_api:
dependency: "direct main"
description:
path: "."
ref: main
resolved-ref: "55f96368b7465eec2e5e81774f9f2a7b18acc4ab"
url: "https://github.com/KRTirtho/dab_music_api.git"
source: git
version: "0.1.0"
dart_des: dart_des:
dependency: transitive dependency: transitive
description: description:
@ -2055,14 +2046,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.0" version: "4.1.0"
retrofit:
dependency: transitive
description:
name: retrofit
sha256: "699cf44ec6c7fc7d248740932eca75d334e36bdafe0a8b3e9ff93100591c8a25"
url: "https://pub.dev"
source: hosted
version: "4.7.2"
riverpod: riverpod:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -24,10 +24,6 @@ dependencies:
bonsoir: ^5.1.10 bonsoir: ^5.1.10
cached_network_image: ^3.3.1 cached_network_image: ^3.3.1
connectivity_plus: ^6.1.2 connectivity_plus: ^6.1.2
dab_music_api:
git:
url: https://github.com/KRTirtho/dab_music_api.git
ref: main
desktop_webview_window: desktop_webview_window:
git: git:
path: packages/desktop_webview_window path: packages/desktop_webview_window

View File

@ -1,147 +1,118 @@
{ {
"ar": [ "ar": [
"source", "source"
"uncompressed"
], ],
"bn": [ "bn": [
"source", "source"
"uncompressed"
], ],
"ca": [ "ca": [
"source", "source"
"uncompressed"
], ],
"cs": [ "cs": [
"source", "source"
"uncompressed"
], ],
"de": [ "de": [
"source", "source"
"uncompressed"
], ],
"es": [ "es": [
"source", "source"
"uncompressed"
], ],
"eu": [ "eu": [
"source", "source"
"uncompressed"
], ],
"fa": [ "fa": [
"source", "source"
"uncompressed"
], ],
"fi": [ "fi": [
"source", "source"
"uncompressed"
], ],
"fr": [ "fr": [
"source", "source"
"uncompressed"
], ],
"hi": [ "hi": [
"source", "source"
"uncompressed"
], ],
"id": [ "id": [
"source", "source"
"uncompressed"
], ],
"it": [ "it": [
"source", "source"
"uncompressed"
], ],
"ja": [ "ja": [
"source", "source"
"uncompressed"
], ],
"ka": [ "ka": [
"source", "source"
"uncompressed"
], ],
"ko": [ "ko": [
"source", "source"
"uncompressed"
], ],
"ne": [ "ne": [
"source", "source"
"uncompressed"
], ],
"nl": [ "nl": [
"audio_source", "audio_source",
"source", "source"
"uncompressed"
], ],
"pl": [ "pl": [
"source", "source"
"uncompressed"
], ],
"pt": [ "pt": [
"source", "source"
"uncompressed"
], ],
"ru": [ "ru": [
"source", "source"
"uncompressed"
], ],
"ta": [ "ta": [
"source", "source"
"uncompressed"
], ],
"th": [ "th": [
"source", "source"
"uncompressed"
], ],
"tl": [ "tl": [
"source", "source"
"uncompressed"
], ],
"tr": [ "tr": [
"source", "source"
"uncompressed"
], ],
"uk": [ "uk": [
"source", "source"
"uncompressed"
], ],
"vi": [ "vi": [
"source", "source"
"uncompressed"
], ],
"zh": [ "zh": [
"source", "source"
"uncompressed"
], ],
"zh_TW": [ "zh_TW": [
"source", "source"
"uncompressed"
] ]
} }