61 lines
2.0 KiB
Dart
61 lines
2.0 KiB
Dart
import 'package:json_annotation/json_annotation.dart';
|
|
|
|
import '../utils/json_utils.dart';
|
|
import 'media_stream.dart';
|
|
|
|
part 'media_part.g.dart';
|
|
|
|
/// One physical file part of a [MediaVersion]. A movie typically has a single
|
|
/// part; some Plex multi-part files (CD1/CD2) and DVD/BluRay rips can have
|
|
/// several. Jellyfin items always map to a single part per media source.
|
|
@JsonSerializable(includeIfNull: false)
|
|
class MediaPart {
|
|
/// Backend-opaque part identifier.
|
|
@JsonKey(fromJson: stringOrEmpty)
|
|
final String id;
|
|
|
|
/// Backend-specific path used to construct a direct stream URL — e.g. Plex's
|
|
/// `/library/parts/123/file.mkv` or Jellyfin's `/Videos/{id}/stream`. The
|
|
/// per-backend client is responsible for prefixing the base URL and
|
|
/// appending auth.
|
|
final String? streamPath;
|
|
|
|
/// The server-side file path backing this part. The identity signal for
|
|
/// "same underlying file": Plex represents a multi-episode file
|
|
/// (`S02E24-E25.mkv`) as distinct episodes whose parts have *different*
|
|
/// part ids but the same [file] (#1500). May be absent (e.g. Plex hides
|
|
/// paths from restricted users), in which case same-file detection
|
|
/// degrades gracefully.
|
|
final String? file;
|
|
|
|
@JsonKey(fromJson: flexibleInt)
|
|
final int? sizeBytes;
|
|
final String? container;
|
|
@JsonKey(fromJson: flexibleInt)
|
|
final int? durationMs;
|
|
final bool? accessible;
|
|
final bool? exists;
|
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
final List<MediaStream> streams;
|
|
|
|
const MediaPart({
|
|
required this.id,
|
|
this.streamPath,
|
|
this.file,
|
|
this.sizeBytes,
|
|
this.container,
|
|
this.durationMs,
|
|
this.accessible,
|
|
this.exists,
|
|
this.streams = const [],
|
|
});
|
|
|
|
factory MediaPart.fromJson(Map<String, dynamic> json) => _$MediaPartFromJson(json);
|
|
|
|
Map<String, dynamic> toJson() => _$MediaPartToJson(this);
|
|
|
|
/// Defaults to true when fields are absent. Plex sets these only when the
|
|
/// metadata request includes `checkFiles=1`.
|
|
bool get isPlayable => accessible != false && exists != false;
|
|
}
|