mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
chore: make playback working
This commit is contained in:
parent
86e55f7a3d
commit
41cc79b5e6
File diff suppressed because one or more lines are too long
@ -9,7 +9,6 @@ import 'package:spotube/extensions/duration.dart';
|
|||||||
import 'package:spotube/models/metadata/metadata.dart';
|
import 'package:spotube/models/metadata/metadata.dart';
|
||||||
import 'package:spotube/models/playback/track_sources.dart';
|
import 'package:spotube/models/playback/track_sources.dart';
|
||||||
import 'package:spotube/provider/server/track_sources.dart';
|
import 'package:spotube/provider/server/track_sources.dart';
|
||||||
import 'package:spotube/services/sourced_track/sourced_track.dart';
|
|
||||||
|
|
||||||
class TrackDetailsDialog extends HookConsumerWidget {
|
class TrackDetailsDialog extends HookConsumerWidget {
|
||||||
final SpotubeFullTrackObject track;
|
final SpotubeFullTrackObject track;
|
||||||
@ -59,12 +58,13 @@ class TrackDetailsDialog extends HookConsumerWidget {
|
|||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
context.l10n.channel: Text(sourceInfo.artists),
|
context.l10n.channel: Text(sourceInfo.artists),
|
||||||
context.l10n.streamUrl: Hyperlink(
|
if (sourcedTrack.asData?.value.url != null)
|
||||||
(track as SourcedTrack).url,
|
context.l10n.streamUrl: Hyperlink(
|
||||||
(track as SourcedTrack).url,
|
sourcedTrack.asData!.value.url,
|
||||||
maxLines: 2,
|
sourcedTrack.asData!.value.url,
|
||||||
overflow: TextOverflow.ellipsis,
|
maxLines: 2,
|
||||||
),
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
|
@ -214,14 +214,12 @@ class TrackOptions extends HookConsumerWidget {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
final progressNotifier = useMemoized(() {
|
final progressNotifier = useMemoized(() {
|
||||||
if (track is! SpotubeFullTrackObject) {
|
if (track is SpotubeLocalTrackObject) {
|
||||||
return throw Exception(
|
return null;
|
||||||
"Invalid usage of `progressNotifierFuture`. Track must be a SpotubeFullTrackObject to get download progress",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return downloadManager
|
return downloadManager
|
||||||
.getProgressNotifier(track as SpotubeFullTrackObject);
|
.getProgressNotifier(track as SpotubeFullTrackObject);
|
||||||
});
|
}, [downloadManager, track]);
|
||||||
|
|
||||||
final isLocalTrack = track is SpotubeLocalTrackObject;
|
final isLocalTrack = track is SpotubeLocalTrackObject;
|
||||||
|
|
||||||
@ -346,7 +344,7 @@ class TrackOptions extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
icon: icon ?? const Icon(SpotubeIcons.moreHorizontal),
|
icon: icon ?? const Icon(SpotubeIcons.moreHorizontal),
|
||||||
variance: ButtonVariance.outline,
|
variance: ButtonVariance.ghost,
|
||||||
headings: [
|
headings: [
|
||||||
Basic(
|
Basic(
|
||||||
leading: AspectRatio(
|
leading: AspectRatio(
|
||||||
|
@ -2930,7 +2930,9 @@ class $AudioPlayerStateTableTable extends AudioPlayerStateTable
|
|||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<List<SpotubeTrackObject>, String>
|
late final GeneratedColumnWithTypeConverter<List<SpotubeTrackObject>, String>
|
||||||
tracks = GeneratedColumn<String>('tracks', aliasedName, false,
|
tracks = GeneratedColumn<String>('tracks', aliasedName, false,
|
||||||
type: DriftSqlType.string, requiredDuringInsert: true)
|
type: DriftSqlType.string,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultValue: const Constant("[]"))
|
||||||
.withConverter<List<SpotubeTrackObject>>(
|
.withConverter<List<SpotubeTrackObject>>(
|
||||||
$AudioPlayerStateTableTable.$convertertracks);
|
$AudioPlayerStateTableTable.$convertertracks);
|
||||||
static const VerificationMeta _currentIndexMeta =
|
static const VerificationMeta _currentIndexMeta =
|
||||||
@ -2938,7 +2940,9 @@ class $AudioPlayerStateTableTable extends AudioPlayerStateTable
|
|||||||
@override
|
@override
|
||||||
late final GeneratedColumn<int> currentIndex = GeneratedColumn<int>(
|
late final GeneratedColumn<int> currentIndex = GeneratedColumn<int>(
|
||||||
'current_index', aliasedName, false,
|
'current_index', aliasedName, false,
|
||||||
type: DriftSqlType.int, requiredDuringInsert: true);
|
type: DriftSqlType.int,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultValue: const Constant(0));
|
||||||
@override
|
@override
|
||||||
List<GeneratedColumn> get $columns =>
|
List<GeneratedColumn> get $columns =>
|
||||||
[id, playing, loopMode, shuffled, collections, tracks, currentIndex];
|
[id, playing, loopMode, shuffled, collections, tracks, currentIndex];
|
||||||
@ -2976,8 +2980,6 @@ class $AudioPlayerStateTableTable extends AudioPlayerStateTable
|
|||||||
_currentIndexMeta,
|
_currentIndexMeta,
|
||||||
currentIndex.isAcceptableOrUnknown(
|
currentIndex.isAcceptableOrUnknown(
|
||||||
data['current_index']!, _currentIndexMeta));
|
data['current_index']!, _currentIndexMeta));
|
||||||
} else if (isInserting) {
|
|
||||||
context.missing(_currentIndexMeta);
|
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
@ -3189,14 +3191,12 @@ class AudioPlayerStateTableCompanion
|
|||||||
required PlaylistMode loopMode,
|
required PlaylistMode loopMode,
|
||||||
required bool shuffled,
|
required bool shuffled,
|
||||||
required List<String> collections,
|
required List<String> collections,
|
||||||
required List<SpotubeTrackObject> tracks,
|
this.tracks = const Value.absent(),
|
||||||
required int currentIndex,
|
this.currentIndex = const Value.absent(),
|
||||||
}) : playing = Value(playing),
|
}) : playing = Value(playing),
|
||||||
loopMode = Value(loopMode),
|
loopMode = Value(loopMode),
|
||||||
shuffled = Value(shuffled),
|
shuffled = Value(shuffled),
|
||||||
collections = Value(collections),
|
collections = Value(collections);
|
||||||
tracks = Value(tracks),
|
|
||||||
currentIndex = Value(currentIndex);
|
|
||||||
static Insertable<AudioPlayerStateTableData> custom({
|
static Insertable<AudioPlayerStateTableData> custom({
|
||||||
Expression<int>? id,
|
Expression<int>? id,
|
||||||
Expression<bool>? playing,
|
Expression<bool>? playing,
|
||||||
@ -5751,8 +5751,8 @@ typedef $$AudioPlayerStateTableTableCreateCompanionBuilder
|
|||||||
required PlaylistMode loopMode,
|
required PlaylistMode loopMode,
|
||||||
required bool shuffled,
|
required bool shuffled,
|
||||||
required List<String> collections,
|
required List<String> collections,
|
||||||
required List<SpotubeTrackObject> tracks,
|
Value<List<SpotubeTrackObject>> tracks,
|
||||||
required int currentIndex,
|
Value<int> currentIndex,
|
||||||
});
|
});
|
||||||
typedef $$AudioPlayerStateTableTableUpdateCompanionBuilder
|
typedef $$AudioPlayerStateTableTableUpdateCompanionBuilder
|
||||||
= AudioPlayerStateTableCompanion Function({
|
= AudioPlayerStateTableCompanion Function({
|
||||||
@ -5922,8 +5922,8 @@ class $$AudioPlayerStateTableTableTableManager extends RootTableManager<
|
|||||||
required PlaylistMode loopMode,
|
required PlaylistMode loopMode,
|
||||||
required bool shuffled,
|
required bool shuffled,
|
||||||
required List<String> collections,
|
required List<String> collections,
|
||||||
required List<SpotubeTrackObject> tracks,
|
Value<List<SpotubeTrackObject>> tracks = const Value.absent(),
|
||||||
required int currentIndex,
|
Value<int> currentIndex = const Value.absent(),
|
||||||
}) =>
|
}) =>
|
||||||
AudioPlayerStateTableCompanion.insert(
|
AudioPlayerStateTableCompanion.insert(
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -1921,10 +1921,10 @@ class Shape14 extends i0.VersionedTable {
|
|||||||
|
|
||||||
i1.GeneratedColumn<String> _column_57(String aliasedName) =>
|
i1.GeneratedColumn<String> _column_57(String aliasedName) =>
|
||||||
i1.GeneratedColumn<String>('tracks', aliasedName, false,
|
i1.GeneratedColumn<String>('tracks', aliasedName, false,
|
||||||
type: i1.DriftSqlType.string);
|
type: i1.DriftSqlType.string, defaultValue: const Constant("[]"));
|
||||||
i1.GeneratedColumn<int> _column_58(String aliasedName) =>
|
i1.GeneratedColumn<int> _column_58(String aliasedName) =>
|
||||||
i1.GeneratedColumn<int>('current_index', aliasedName, false,
|
i1.GeneratedColumn<int>('current_index', aliasedName, false,
|
||||||
type: i1.DriftSqlType.int);
|
type: i1.DriftSqlType.int, defaultValue: const Constant(0));
|
||||||
|
|
||||||
class Shape15 extends i0.VersionedTable {
|
class Shape15 extends i0.VersionedTable {
|
||||||
Shape15({required super.source, required super.alias}) : super.aliased();
|
Shape15({required super.source, required super.alias}) : super.aliased();
|
||||||
|
@ -6,9 +6,10 @@ class AudioPlayerStateTable extends Table {
|
|||||||
TextColumn get loopMode => textEnum<PlaylistMode>()();
|
TextColumn get loopMode => textEnum<PlaylistMode>()();
|
||||||
BoolColumn get shuffled => boolean()();
|
BoolColumn get shuffled => boolean()();
|
||||||
TextColumn get collections => text().map(const StringListConverter())();
|
TextColumn get collections => text().map(const StringListConverter())();
|
||||||
TextColumn get tracks =>
|
TextColumn get tracks => text()
|
||||||
text().map(const SpotubeTrackObjectListConverter())();
|
.map(const SpotubeTrackObjectListConverter())
|
||||||
IntColumn get currentIndex => integer()();
|
.withDefault(const Constant("[]"))();
|
||||||
|
IntColumn get currentIndex => integer().withDefault(const Constant(0))();
|
||||||
}
|
}
|
||||||
|
|
||||||
class SpotubeTrackObjectListConverter
|
class SpotubeTrackObjectListConverter
|
||||||
|
@ -9,6 +9,8 @@ part 'track_sources.g.dart';
|
|||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class TrackSourceQuery with _$TrackSourceQuery {
|
class TrackSourceQuery with _$TrackSourceQuery {
|
||||||
|
TrackSourceQuery._();
|
||||||
|
|
||||||
factory TrackSourceQuery({
|
factory TrackSourceQuery({
|
||||||
required String id,
|
required String id,
|
||||||
required String title,
|
required String title,
|
||||||
@ -37,10 +39,23 @@ class TrackSourceQuery with _$TrackSourceQuery {
|
|||||||
/// Parses [SpotubeMedia]'s [uri] property to create a [TrackSourceQuery].
|
/// Parses [SpotubeMedia]'s [uri] property to create a [TrackSourceQuery].
|
||||||
factory TrackSourceQuery.parseUri(String url) {
|
factory TrackSourceQuery.parseUri(String url) {
|
||||||
final uri = Uri.parse(url);
|
final uri = Uri.parse(url);
|
||||||
return TrackSourceQuery.fromJson({
|
return TrackSourceQuery(
|
||||||
"id": uri.pathSegments.last,
|
id: uri.pathSegments.last,
|
||||||
...uri.queryParameters,
|
title: uri.queryParameters['title'] ?? '',
|
||||||
});
|
artists: uri.queryParameters['artists']?.split(',') ?? [],
|
||||||
|
album: uri.queryParameters['album'] ?? '',
|
||||||
|
durationMs: int.tryParse(uri.queryParameters['durationMs'] ?? '0') ?? 0,
|
||||||
|
isrc: uri.queryParameters['isrc'] ?? '',
|
||||||
|
explicit: uri.queryParameters['explicit']?.toLowerCase() == 'true',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String queryString() {
|
||||||
|
return toJson()
|
||||||
|
.entries
|
||||||
|
.map((e) =>
|
||||||
|
"${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value is List<String> ? e.value.join(",") : e.value.toString())}")
|
||||||
|
.join("&");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ class __$$TrackSourceQueryImplCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class _$TrackSourceQueryImpl implements _TrackSourceQuery {
|
class _$TrackSourceQueryImpl extends _TrackSourceQuery {
|
||||||
_$TrackSourceQueryImpl(
|
_$TrackSourceQueryImpl(
|
||||||
{required this.id,
|
{required this.id,
|
||||||
required this.title,
|
required this.title,
|
||||||
@ -193,7 +193,8 @@ class _$TrackSourceQueryImpl implements _TrackSourceQuery {
|
|||||||
required this.durationMs,
|
required this.durationMs,
|
||||||
required this.isrc,
|
required this.isrc,
|
||||||
required this.explicit})
|
required this.explicit})
|
||||||
: _artists = artists;
|
: _artists = artists,
|
||||||
|
super._();
|
||||||
|
|
||||||
factory _$TrackSourceQueryImpl.fromJson(Map<String, dynamic> json) =>
|
factory _$TrackSourceQueryImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
_$$TrackSourceQueryImplFromJson(json);
|
_$$TrackSourceQueryImplFromJson(json);
|
||||||
@ -269,7 +270,7 @@ class _$TrackSourceQueryImpl implements _TrackSourceQuery {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class _TrackSourceQuery implements TrackSourceQuery {
|
abstract class _TrackSourceQuery extends TrackSourceQuery {
|
||||||
factory _TrackSourceQuery(
|
factory _TrackSourceQuery(
|
||||||
{required final String id,
|
{required final String id,
|
||||||
required final String title,
|
required final String title,
|
||||||
@ -278,6 +279,7 @@ abstract class _TrackSourceQuery implements TrackSourceQuery {
|
|||||||
required final int durationMs,
|
required final int durationMs,
|
||||||
required final String isrc,
|
required final String isrc,
|
||||||
required final bool explicit}) = _$TrackSourceQueryImpl;
|
required final bool explicit}) = _$TrackSourceQueryImpl;
|
||||||
|
_TrackSourceQuery._() : super._();
|
||||||
|
|
||||||
factory _TrackSourceQuery.fromJson(Map<String, dynamic> json) =
|
factory _TrackSourceQuery.fromJson(Map<String, dynamic> json) =
|
||||||
_$TrackSourceQueryImpl.fromJson;
|
_$TrackSourceQueryImpl.fromJson;
|
||||||
|
@ -62,10 +62,10 @@ class PlaylistCard extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<SpotubeTrackObject>> fetchAllTracks() async {
|
Future<List<SpotubeTrackObject>> fetchAllTracks() async {
|
||||||
final initialTracks = await fetchInitialTracks();
|
await fetchInitialTracks();
|
||||||
|
|
||||||
if (playlist.id == 'user-liked-tracks') {
|
if (playlist.id == 'user-liked-tracks') {
|
||||||
return initialTracks;
|
return ref.read(metadataPluginSavedTracksProvider.notifier).fetchAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ref
|
return ref
|
||||||
|
@ -2,7 +2,6 @@ import 'dart:math';
|
|||||||
|
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:media_kit/media_kit.dart' hide Track;
|
|
||||||
import 'package:spotube/extensions/list.dart';
|
import 'package:spotube/extensions/list.dart';
|
||||||
import 'package:spotube/models/database/database.dart';
|
import 'package:spotube/models/database/database.dart';
|
||||||
import 'package:spotube/models/metadata/metadata.dart';
|
import 'package:spotube/models/metadata/metadata.dart';
|
||||||
@ -48,8 +47,8 @@ class AudioPlayerNotifier extends Notifier<AudioPlayerState> {
|
|||||||
loopMode: audioPlayer.loopMode,
|
loopMode: audioPlayer.loopMode,
|
||||||
shuffled: audioPlayer.isShuffled,
|
shuffled: audioPlayer.isShuffled,
|
||||||
collections: <String>[],
|
collections: <String>[],
|
||||||
tracks: <SpotubeTrackObject>[],
|
tracks: const Value(<SpotubeTrackObject>[]),
|
||||||
currentIndex: 0,
|
currentIndex: const Value(0),
|
||||||
id: const Value(0),
|
id: const Value(0),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -143,10 +142,12 @@ class AudioPlayerNotifier extends Notifier<AudioPlayerState> {
|
|||||||
final queries = playlist.medias
|
final queries = playlist.medias
|
||||||
.map((media) => TrackSourceQuery.parseUri(media.uri))
|
.map((media) => TrackSourceQuery.parseUri(media.uri))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
final tracks = queries
|
final tracks = queries
|
||||||
.map((query) => state.tracks.firstWhere(
|
.map(
|
||||||
(element) => element.id == query.id,
|
(query) => state.tracks
|
||||||
))
|
.firstWhere((element) => element.id == query.id),
|
||||||
|
)
|
||||||
.toList();
|
.toList();
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
tracks: tracks,
|
tracks: tracks,
|
||||||
@ -249,6 +250,10 @@ class AudioPlayerNotifier extends Notifier<AudioPlayerState> {
|
|||||||
|
|
||||||
if (_blacklist.contains(track)) return;
|
if (_blacklist.contains(track)) return;
|
||||||
if (state.tracks.any((element) => _compareTracks(element, track))) return;
|
if (state.tracks.any((element) => _compareTracks(element, track))) return;
|
||||||
|
|
||||||
|
state = state.copyWith(
|
||||||
|
tracks: [...state.tracks, track],
|
||||||
|
);
|
||||||
await audioPlayer.addTrack(SpotubeMedia(track));
|
await audioPlayer.addTrack(SpotubeMedia(track));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,6 +261,9 @@ class AudioPlayerNotifier extends Notifier<AudioPlayerState> {
|
|||||||
_assertAllowedTracks(tracks);
|
_assertAllowedTracks(tracks);
|
||||||
|
|
||||||
tracks = _blacklist.filter(tracks).toList();
|
tracks = _blacklist.filter(tracks).toList();
|
||||||
|
state = state.copyWith(
|
||||||
|
tracks: [...state.tracks, ...tracks],
|
||||||
|
);
|
||||||
for (final track in tracks) {
|
for (final track in tracks) {
|
||||||
await audioPlayer.addTrack(SpotubeMedia(track));
|
await audioPlayer.addTrack(SpotubeMedia(track));
|
||||||
}
|
}
|
||||||
@ -313,10 +321,15 @@ class AudioPlayerNotifier extends Notifier<AudioPlayerState> {
|
|||||||
|
|
||||||
if (medias.isEmpty) return;
|
if (medias.isEmpty) return;
|
||||||
|
|
||||||
await removeCollections(state.collections);
|
state = state.copyWith(
|
||||||
|
// These are filtered tracks as well
|
||||||
|
tracks: medias.map((media) => media.track).toList(),
|
||||||
|
currentIndex: initialIndex,
|
||||||
|
collections: [],
|
||||||
|
);
|
||||||
|
|
||||||
await audioPlayer.openPlaylist(
|
await audioPlayer.openPlaylist(
|
||||||
medias.map((s) => s as Media).toList(),
|
medias,
|
||||||
initialIndex: initialIndex,
|
initialIndex: initialIndex,
|
||||||
autoPlay: autoPlay,
|
autoPlay: autoPlay,
|
||||||
);
|
);
|
||||||
|
@ -19,8 +19,6 @@ part 'audio_player_impl.dart';
|
|||||||
class SpotubeMedia extends mk.Media {
|
class SpotubeMedia extends mk.Media {
|
||||||
static int serverPort = 0;
|
static int serverPort = 0;
|
||||||
|
|
||||||
final SpotubeTrackObject track;
|
|
||||||
|
|
||||||
static String get _host =>
|
static String get _host =>
|
||||||
kIsWindows ? "localhost" : InternetAddress.anyIPv4.address;
|
kIsWindows ? "localhost" : InternetAddress.anyIPv4.address;
|
||||||
|
|
||||||
@ -29,10 +27,11 @@ class SpotubeMedia extends mk.Media {
|
|||||||
|
|
||||||
return params.entries
|
return params.entries
|
||||||
.map((e) =>
|
.map((e) =>
|
||||||
"${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}")
|
"${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value is List<String> ? e.value.join(",") : e.value.toString())}")
|
||||||
.join("&");
|
.join("&");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final SpotubeTrackObject track;
|
||||||
SpotubeMedia(
|
SpotubeMedia(
|
||||||
this.track, {
|
this.track, {
|
||||||
Map<String, dynamic>? extras,
|
Map<String, dynamic>? extras,
|
||||||
@ -47,32 +46,6 @@ class SpotubeMedia extends mk.Media {
|
|||||||
? track.path
|
? track.path
|
||||||
: "http://$_host:$serverPort/stream/${track.id}?${_queries(track as SpotubeFullTrackObject)}",
|
: "http://$_host:$serverPort/stream/${track.id}?${_queries(track as SpotubeFullTrackObject)}",
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
|
||||||
String get uri {
|
|
||||||
return switch (track) {
|
|
||||||
/// [super.uri] must be used instead of [track.path] to prevent wrong
|
|
||||||
/// path format exceptions in Windows causing [extras] to be null
|
|
||||||
SpotubeLocalTrackObject() => super.uri,
|
|
||||||
_ => "http://$_host:"
|
|
||||||
"$serverPort/stream/${track.id}",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// @override
|
|
||||||
// operator ==(Object other) {
|
|
||||||
// if (other is! SpotubeMedia) return false;
|
|
||||||
|
|
||||||
// final isLocal = track is LocalTrack && other.track is LocalTrack;
|
|
||||||
// return isLocal
|
|
||||||
// ? (other.track as LocalTrack).path == (track as LocalTrack).path
|
|
||||||
// : other.track.id == track.id;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @override
|
|
||||||
// int get hashCode => track is LocalTrack
|
|
||||||
// ? (track as LocalTrack).path.hashCode
|
|
||||||
// : track.id.hashCode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class AudioPlayerInterface {
|
abstract class AudioPlayerInterface {
|
||||||
|
@ -106,23 +106,27 @@ class MetadataPluginUserEndpoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<bool>> isSavedTracks(List<String> ids) async {
|
Future<List<bool>> isSavedTracks(List<String> ids) async {
|
||||||
return await hetuMetadataUser.invoke(
|
final values = await hetuMetadataUser.invoke(
|
||||||
"isSavedTracks",
|
"isSavedTracks",
|
||||||
positionalArgs: [ids],
|
positionalArgs: [ids],
|
||||||
) as List<bool>;
|
);
|
||||||
|
return (values as List).cast<bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<bool>> isSavedAlbums(List<String> ids) async {
|
Future<List<bool>> isSavedAlbums(List<String> ids) async {
|
||||||
return await hetuMetadataUser.invoke(
|
final values = await hetuMetadataUser.invoke(
|
||||||
"isSavedAlbums",
|
"isSavedAlbums",
|
||||||
positionalArgs: [ids],
|
positionalArgs: [ids],
|
||||||
) as List<bool>;
|
) as List;
|
||||||
|
return values.cast<bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<bool>> isSavedArtists(List<String> ids) async {
|
Future<List<bool>> isSavedArtists(List<String> ids) async {
|
||||||
return await hetuMetadataUser.invoke(
|
final values = await hetuMetadataUser.invoke(
|
||||||
"isSavedArtists",
|
"isSavedArtists",
|
||||||
positionalArgs: [ids],
|
positionalArgs: [ids],
|
||||||
) as List<bool>;
|
) as List;
|
||||||
|
|
||||||
|
return values.cast<bool>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,14 +109,15 @@ class YoutubeSourcedTrack extends SourcedTrack {
|
|||||||
return manifest.audioOnly.map((streamInfo) {
|
return manifest.audioOnly.map((streamInfo) {
|
||||||
return TrackSource(
|
return TrackSource(
|
||||||
url: streamInfo.url.toString(),
|
url: streamInfo.url.toString(),
|
||||||
quality: streamInfo.qualityLabel == "AUDIO_QUALITY_HIGH"
|
quality: switch (streamInfo.qualityLabel) {
|
||||||
? SourceQualities.high
|
"medium" => SourceQualities.medium,
|
||||||
: streamInfo.qualityLabel == "AUDIO_QUALITY_MEDIUM"
|
"high" => SourceQualities.high,
|
||||||
? SourceQualities.medium
|
"low" => SourceQualities.low,
|
||||||
: SourceQualities.low,
|
_ => SourceQualities.high,
|
||||||
codec: streamInfo.codec.mimeType == "audio/mp4"
|
},
|
||||||
? SourceCodecs.m4a
|
codec: streamInfo.codec.mimeType == "audio/webm"
|
||||||
: SourceCodecs.weba,
|
? SourceCodecs.weba
|
||||||
|
: SourceCodecs.m4a,
|
||||||
bitrate: streamInfo.bitrate.bitsPerSecond.toString(),
|
bitrate: streamInfo.bitrate.bitsPerSecond.toString(),
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
@ -2813,10 +2813,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: youtube_explode_dart
|
name: youtube_explode_dart
|
||||||
sha256: "3e1f1b5aa575670afc9dbc96cece23af78f9ec2044ce0d9f70d136fff6c53b53"
|
sha256: "8db47e0f947598f6aa29d2862efb98b92af0c78990d4b23c224f3475c556b47b"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.0-dev.1"
|
version: "2.4.2"
|
||||||
yt_dlp_dart:
|
yt_dlp_dart:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -129,7 +129,7 @@ dependencies:
|
|||||||
wikipedia_api: ^0.1.0
|
wikipedia_api: ^0.1.0
|
||||||
win32_registry: ^1.1.5
|
win32_registry: ^1.1.5
|
||||||
window_manager: ^0.4.3
|
window_manager: ^0.4.3
|
||||||
youtube_explode_dart: ^2.4.0-dev.1
|
youtube_explode_dart: ^2.4.2
|
||||||
yt_dlp_dart:
|
yt_dlp_dart:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/KRTirtho/yt_dlp_dart.git
|
url: https://github.com/KRTirtho/yt_dlp_dart.git
|
||||||
|
@ -2301,10 +2301,14 @@ class AudioPlayerStateTable extends Table
|
|||||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||||
late final GeneratedColumn<String> tracks = GeneratedColumn<String>(
|
late final GeneratedColumn<String> tracks = GeneratedColumn<String>(
|
||||||
'tracks', aliasedName, false,
|
'tracks', aliasedName, false,
|
||||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
type: DriftSqlType.string,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultValue: const Constant("[]"));
|
||||||
late final GeneratedColumn<int> currentIndex = GeneratedColumn<int>(
|
late final GeneratedColumn<int> currentIndex = GeneratedColumn<int>(
|
||||||
'current_index', aliasedName, false,
|
'current_index', aliasedName, false,
|
||||||
type: DriftSqlType.int, requiredDuringInsert: true);
|
type: DriftSqlType.int,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultValue: const Constant(0));
|
||||||
@override
|
@override
|
||||||
List<GeneratedColumn> get $columns =>
|
List<GeneratedColumn> get $columns =>
|
||||||
[id, playing, loopMode, shuffled, collections, tracks, currentIndex];
|
[id, playing, loopMode, shuffled, collections, tracks, currentIndex];
|
||||||
@ -2499,14 +2503,12 @@ class AudioPlayerStateTableCompanion
|
|||||||
required String loopMode,
|
required String loopMode,
|
||||||
required bool shuffled,
|
required bool shuffled,
|
||||||
required String collections,
|
required String collections,
|
||||||
required String tracks,
|
this.tracks = const Value.absent(),
|
||||||
required int currentIndex,
|
this.currentIndex = const Value.absent(),
|
||||||
}) : playing = Value(playing),
|
}) : playing = Value(playing),
|
||||||
loopMode = Value(loopMode),
|
loopMode = Value(loopMode),
|
||||||
shuffled = Value(shuffled),
|
shuffled = Value(shuffled),
|
||||||
collections = Value(collections),
|
collections = Value(collections);
|
||||||
tracks = Value(tracks),
|
|
||||||
currentIndex = Value(currentIndex);
|
|
||||||
static Insertable<AudioPlayerStateTableData> custom({
|
static Insertable<AudioPlayerStateTableData> custom({
|
||||||
Expression<int>? id,
|
Expression<int>? id,
|
||||||
Expression<bool>? playing,
|
Expression<bool>? playing,
|
||||||
|
Loading…
Reference in New Issue
Block a user