| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- import 'package:flutter/foundation.dart';
- import 'media_playback.dart';
- /// One track in the native Jellyfin playback queue.
- @immutable
- class JellyfinQueueItem {
- const JellyfinQueueItem({
- required this.trackId,
- required this.mediaSourceId,
- required this.url,
- required this.title,
- required this.artist,
- required this.album,
- required this.durationMs,
- required this.index,
- });
- final String trackId;
- final String mediaSourceId;
- final String url;
- final String title;
- final String artist;
- final String album;
- final int durationMs;
- final int index;
- Map<String, Object?> toMap() => {
- 'trackId': trackId,
- 'mediaSourceId': mediaSourceId,
- 'url': url,
- 'title': title,
- 'artist': artist,
- 'album': album,
- 'durationMs': durationMs,
- 'index': index,
- };
- }
- /// Everything the native service needs to start one album. [authorization] and
- /// [accessToken] are kept in memory and are never logged or persisted.
- @immutable
- class JellyfinPlaybackQueue {
- const JellyfinPlaybackQueue({
- required this.baseUrl,
- required this.authorization,
- required this.accessToken,
- required this.userId,
- required this.deviceId,
- required this.playSessionId,
- required this.albumId,
- required this.albumName,
- required this.artistName,
- required this.items,
- this.artwork,
- });
- final Uri baseUrl;
- final String authorization;
- final String accessToken;
- final String userId;
- final String deviceId;
- final String playSessionId;
- final String albumId;
- final String albumName;
- final String artistName;
- final List<JellyfinQueueItem> items;
- final Uint8List? artwork;
- Map<String, Object?> toMap() => {
- 'baseUrl': baseUrl.toString(),
- 'authorization': authorization,
- 'accessToken': accessToken,
- 'userId': userId,
- 'deviceId': deviceId,
- 'playSessionId': playSessionId,
- 'albumId': albumId,
- 'albumName': albumName,
- 'artistName': artistName,
- 'artwork': artwork,
- 'items': items.map((item) => item.toMap()).toList(growable: false),
- };
- }
- /// The native player's current state. Positions are milliseconds.
- @immutable
- class JellyfinPlaybackSnapshot {
- const JellyfinPlaybackSnapshot({
- this.available = false,
- this.playing = false,
- this.buffering = false,
- this.itemId,
- this.albumId,
- this.title,
- this.artist,
- this.album,
- this.durationMs = 0,
- this.positionMs = 0,
- this.index = 0,
- this.hasPrevious = false,
- this.hasNext = false,
- this.error,
- });
- static const empty = JellyfinPlaybackSnapshot();
- final bool available;
- final bool playing;
- final bool buffering;
- final String? itemId;
- final String? albumId;
- final String? title;
- final String? artist;
- final String? album;
- final int durationMs;
- final int positionMs;
- final int index;
- final bool hasPrevious;
- final bool hasNext;
- final String? error;
- bool get playingOrBuffering => playing || buffering;
- bool get ended =>
- available && !playing && durationMs > 0 && positionMs >= durationMs - 500;
- double get progress {
- if (durationMs <= 0) return 0;
- return (positionMs / durationMs).clamp(0.0, 1.0);
- }
- JellyfinPlaybackSnapshot copyWith({
- bool? available,
- bool? playing,
- bool? buffering,
- int? positionMs,
- int? index,
- bool? hasPrevious,
- bool? hasNext,
- String? error,
- }) {
- return JellyfinPlaybackSnapshot(
- available: available ?? this.available,
- playing: playing ?? this.playing,
- buffering: buffering ?? this.buffering,
- itemId: itemId,
- albumId: albumId,
- title: title,
- artist: artist,
- album: album,
- durationMs: durationMs,
- positionMs: positionMs ?? this.positionMs,
- index: index ?? this.index,
- hasPrevious: hasPrevious ?? this.hasPrevious,
- hasNext: hasNext ?? this.hasNext,
- error: error ?? this.error,
- );
- }
- factory JellyfinPlaybackSnapshot.fromMap(Map<dynamic, dynamic> map) {
- int integer(String key) => (map[key] as num?)?.toInt() ?? 0;
- String? string(String key) {
- final value = (map[key] as String?)?.trim();
- return value == null || value.isEmpty ? null : value;
- }
- return JellyfinPlaybackSnapshot(
- available: map['available'] == true,
- playing: map['playing'] == true,
- buffering: map['buffering'] == true,
- itemId: string('itemId'),
- albumId: string('albumId'),
- title: string('title'),
- artist: string('artist'),
- album: string('album'),
- durationMs: integer('durationMs'),
- positionMs: integer('positionMs'),
- index: integer('index'),
- hasPrevious: map['hasPrevious'] == true,
- hasNext: map['hasNext'] == true,
- error: string('error'),
- );
- }
- /// Snapshot consumed by the Home volume card and the existing media widgets.
- MediaPlayback toMediaPlayback() {
- return MediaPlayback(
- hasAccess: available,
- hasSession: available && itemId != null,
- playing: playing,
- title: title,
- artist: artist,
- packageName: 'com.wasp.cardash_launcher',
- durationMs: durationMs,
- positionMs: positionMs,
- );
- }
- @override
- bool operator ==(Object other) {
- return other is JellyfinPlaybackSnapshot &&
- other.available == available &&
- other.playing == playing &&
- other.buffering == buffering &&
- other.itemId == itemId &&
- other.albumId == albumId &&
- other.title == title &&
- other.artist == artist &&
- other.album == album &&
- other.durationMs == durationMs &&
- other.positionMs == positionMs &&
- other.index == index &&
- other.hasPrevious == hasPrevious &&
- other.hasNext == hasNext &&
- other.error == error;
- }
- @override
- int get hashCode => Object.hash(
- available,
- playing,
- buffering,
- itemId,
- albumId,
- title,
- artist,
- album,
- durationMs,
- positionMs,
- index,
- hasPrevious,
- hasNext,
- error,
- );
- }
|