import '../utils/formatters.dart'; import 'plex_media_info.dart'; class PlexFileInfo { // Media level properties final String? container; final String? videoCodec; final String? videoResolution; final String? videoFrameRate; final String? videoProfile; final int? width; final int? height; final double? aspectRatio; final int? bitrate; final int? duration; final String? audioCodec; final String? audioProfile; final int? audioChannels; final bool? optimizedForStreaming; final bool? has64bitOffsets; // Part level properties (file) final String? filePath; final int? fileSize; // Stream level properties (video stream details) final String? colorSpace; final String? colorRange; final String? colorPrimaries; final String? chromaSubsampling; final double? frameRate; final int? bitDepth; final int? videoBitrate; final String? audioChannelLayout; // Multi-track support final List audioTracks; final List subtitleTracks; PlexFileInfo({ this.container, this.videoCodec, this.videoResolution, this.videoFrameRate, this.videoProfile, this.width, this.height, this.aspectRatio, this.bitrate, this.duration, this.audioCodec, this.audioProfile, this.audioChannels, this.optimizedForStreaming, this.has64bitOffsets, this.filePath, this.fileSize, this.colorSpace, this.colorRange, this.colorPrimaries, this.chromaSubsampling, this.frameRate, this.bitDepth, this.videoBitrate, this.audioChannelLayout, this.audioTracks = const [], this.subtitleTracks = const [], }); /// Format file size in human-readable format (GB, MB, KB, bytes) String get fileSizeFormatted { if (fileSize == null) return 'Unknown'; return ByteFormatter.formatBytes(fileSize!, decimals: 2); } /// Format duration in HH:MM:SS or MM:SS format String get durationFormatted { if (duration == null) return 'Unknown'; final seconds = duration! ~/ 1000; final hours = seconds ~/ 3600; final minutes = (seconds % 3600) ~/ 60; final secs = seconds % 60; return hours > 0 ? '${hours}h ${minutes}m ${secs}s' : '${minutes}m ${secs}s'; } /// Format overall bitrate in Mbps or kbps (Plex API returns kbps) String get bitrateFormatted { if (bitrate == null) return 'Unknown'; return ByteFormatter.formatBitrate(bitrate!); } /// Format video stream bitrate in Mbps or kbps String get videoBitrateFormatted { if (videoBitrate == null) return 'Unknown'; return ByteFormatter.formatBitrate(videoBitrate!); } /// Format resolution as widthxheight String get resolutionFormatted { if (width != null && height != null) { return '${width}x$height'; } else if (videoResolution != null) { return videoResolution!; } return 'Unknown'; } /// Format aspect ratio String get aspectRatioFormatted { if (aspectRatio != null) { return aspectRatio!.toStringAsFixed(2); } return 'Unknown'; } /// Format frame rate String get frameRateFormatted { if (frameRate != null) { return '${frameRate!.toStringAsFixed(3)} fps'; } else if (videoFrameRate != null) { return videoFrameRate!; } return 'Unknown'; } /// Format audio channels (e.g., "2 channels (stereo)") String get audioChannelsFormatted { if (audioChannels != null) { String channelText = '$audioChannels channel${audioChannels! > 1 ? 's' : ''}'; if (audioChannelLayout != null) { channelText += ' ($audioChannelLayout)'; } return channelText; } return 'Unknown'; } }