Line data Source code
1 : import 'package:media_source/src/extensions/uri_extensions.dart';
2 : import 'package:media_source/src/media_type.dart';
3 : import 'package:media_source/src/sources/media_source.dart';
4 : import 'package:file_sized/file_sized.dart';
5 : import 'package:file_type_plus/file_type_plus.dart';
6 :
7 : /// Abstract base class for network-based media sources.
8 : ///
9 : /// Represents media accessible via HTTP/HTTPS URLs. Unlike file or memory sources,
10 : /// network media sources do not require loading the full content into memory or
11 : /// file system. They store only the URL and metadata.
12 : ///
13 : /// Useful for:
14 : /// - Streaming media over the network
15 : /// - Playing remote media without downloading
16 : /// - Representing cloud-hosted media
17 : ///
18 : /// Subclasses include:
19 : /// - [VideoNetworkMedia] for video URLs
20 : /// - [AudioNetworkMedia] for audio URLs
21 : /// - [ImageNetworkMedia] for image URLs
22 : /// - [DocumentNetworkMedia] for document URLs
23 : /// - [UnSupportedNetworkMedia] for unclassified URLs
24 : /// - [UrlMedia] for generic URLs
25 : abstract class NetworkMediaSource<M extends FileType> extends MediaSource<M> {
26 : /// The network URI pointing to the media.
27 : final Uri uri;
28 :
29 : /// Internal constructor for creating network media sources.
30 : ///
31 : /// Parameters:
32 : /// - [uri]: The network URI of the media
33 : /// - [name]: Optional custom display name, defaults to filename from URI
34 : /// - [size]: Optional media size
35 : /// - [mimeType]: Optional MIME type, auto-detected from URI path if not provided
36 : /// - [metadata]: Type-specific metadata (VideoType, AudioType, etc.)
37 0 : NetworkMediaSource._({
38 : required this.uri,
39 : String? name,
40 : required super.size,
41 : String? mimeType,
42 : required super.metadata,
43 0 : }) : super(
44 0 : mimeType: mimeType ?? FileUtil.getMimeTypeFromPath(uri.path),
45 0 : name: name ?? uri.fileName,
46 : );
47 :
48 : /// Creates a [NetworkMediaSource] from a URL string.
49 : ///
50 : /// Automatically detects the media type and returns the appropriate subclass.
51 : /// If media type is not provided, it will be determined from the URL path.
52 : ///
53 : /// Parameters:
54 : /// - [url]: The URL string to the media
55 : /// - [name]: Optional custom display name
56 : /// - [size]: Optional media size
57 : /// - [mimeType]: Optional MIME type override
58 : /// - [duration]: Optional duration for audio/video media
59 : /// - [mediaType]: Optional explicit media type
60 : ///
61 : /// Returns the appropriate [NetworkMediaSource] subclass based on media type.
62 : /// Throws an exception if the URL is invalid.
63 0 : static NetworkMediaSource fromUrl(
64 : String url, {
65 : String? name,
66 : FileSize? size,
67 : String? mimeType,
68 : Duration? duration,
69 : FileType? mediaType,
70 : }) {
71 0 : mediaType ??= FileType.fromPath(url, mimeType);
72 0 : final uri = Uri.parse(url);
73 0 : if (mediaType.isAny([FileType.audio])) {
74 0 : return AudioNetworkMedia(
75 : uri,
76 : name: name,
77 : size: size,
78 : mimeType: mimeType,
79 : duration: duration,
80 : );
81 : }
82 0 : if (mediaType.isAny([FileType.video])) {
83 0 : return VideoNetworkMedia(
84 : uri,
85 : name: name,
86 : size: size,
87 : mimeType: mimeType,
88 : duration: duration,
89 : );
90 : }
91 0 : if (mediaType.isAny([FileType.image])) {
92 0 : return ImageNetworkMedia(
93 : uri,
94 : name: name,
95 : size: size,
96 : mimeType: mimeType,
97 : );
98 : }
99 0 : if (mediaType.isAny([FileType.document])) {
100 0 : return DocumentNetworkMedia(
101 : uri,
102 : name: name,
103 : size: size,
104 : mimeType: mimeType,
105 : );
106 : }
107 0 : return UnSupportedNetworkMedia(
108 : uri,
109 : name: name,
110 : size: size,
111 : mimeType: mimeType,
112 : );
113 : }
114 :
115 : /// Safely creates a [NetworkMediaSource] from a URL string or returns null.
116 : ///
117 : /// Similar to [fromUrl] but returns null instead of throwing an exception
118 : /// if the URL is invalid or null.
119 : ///
120 : /// Parameters:
121 : /// - [url]: The URL string to the media, or null
122 : ///
123 : /// Returns a [NetworkMediaSource] or null if the URL is invalid or empty.
124 0 : static NetworkMediaSource? fromUrlOrNull(String? url) {
125 0 : if (url != null && url.isNotEmpty) {
126 : try {
127 0 : return NetworkMediaSource.fromUrl(url);
128 : } catch (e) {
129 : return null;
130 : }
131 : }
132 : return null;
133 : }
134 :
135 : /// Includes the URI in equality comparisons.
136 0 : @override
137 0 : List<Object?> get props => [uri, ...super.props];
138 : }
139 :
140 : /// Represents video URLs (streaming media).
141 : ///
142 : /// Stores video metadata including optional duration information.
143 : /// Supports both Uri and String constructors.
144 : class VideoNetworkMedia extends NetworkMediaSource<VideoType> {
145 : /// Creates a [VideoNetworkMedia] from a Uri object.
146 : ///
147 : /// Parameters:
148 : /// - [uri]: The video URL as a Uri
149 : /// - [duration]: Optional video duration
150 : /// - [mimeType]: Optional MIME type override
151 : /// - [name]: Optional custom display name
152 : /// - [size]: Optional video size
153 0 : VideoNetworkMedia(
154 : Uri uri, {
155 : Duration? duration,
156 : super.mimeType,
157 : super.name,
158 : super.size,
159 0 : }) : super._(
160 : uri: uri,
161 0 : metadata: VideoType(duration),
162 : );
163 :
164 : /// Creates a [VideoNetworkMedia] from a URL string.
165 : ///
166 : /// Convenience constructor that parses a string URL.
167 : ///
168 : /// Parameters:
169 : /// - [url]: The video URL as a string
170 : /// - [duration]: Optional video duration
171 : /// - [mimeType]: Optional MIME type override
172 : /// - [name]: Optional custom display name
173 : /// - [size]: Optional video size
174 0 : VideoNetworkMedia.url(
175 : String url, {
176 : Duration? duration,
177 : super.mimeType,
178 : super.name,
179 : super.size,
180 0 : }) : super._(
181 0 : uri: Uri.parse(url),
182 0 : metadata: VideoType(duration),
183 : );
184 :
185 0 : @override
186 0 : List<Object?> get props => [uri, mimeType, metadata, name, size];
187 : }
188 :
189 : /// Represents audio URLs (streaming media).
190 : ///
191 : /// Stores audio metadata including optional duration information.
192 : /// Supports both Uri and String constructors.
193 : class AudioNetworkMedia extends NetworkMediaSource<AudioType> {
194 : /// Creates an [AudioNetworkMedia] from a Uri object.
195 : ///
196 : /// Parameters:
197 : /// - [uri]: The audio URL as a Uri
198 : /// - [duration]: Optional audio duration
199 : /// - [mimeType]: Optional MIME type override
200 : /// - [name]: Optional custom display name
201 : /// - [size]: Optional audio size
202 0 : AudioNetworkMedia(
203 : Uri uri, {
204 : Duration? duration,
205 : super.mimeType,
206 : super.name,
207 : super.size,
208 0 : }) : super._(
209 : uri: uri,
210 0 : metadata: AudioType(duration),
211 : );
212 :
213 : /// Creates an [AudioNetworkMedia] from a URL string.
214 : ///
215 : /// Convenience constructor that parses a string URL.
216 : ///
217 : /// Parameters:
218 : /// - [url]: The audio URL as a string
219 : /// - [duration]: Optional audio duration
220 : /// - [mimeType]: Optional MIME type override
221 : /// - [name]: Optional custom display name
222 : /// - [size]: Optional audio size
223 0 : AudioNetworkMedia.url(
224 : String url, {
225 : Duration? duration,
226 : super.mimeType,
227 : super.name,
228 : super.size,
229 0 : }) : super._(
230 0 : uri: Uri.parse(url),
231 0 : metadata: AudioType(duration),
232 : );
233 : }
234 :
235 : /// Represents image URLs.
236 : ///
237 : /// Supports both Uri and String constructors for flexible instantiation.
238 : class ImageNetworkMedia extends NetworkMediaSource<ImageType> {
239 : /// Creates an [ImageNetworkMedia] from a Uri object.
240 : ///
241 : /// Parameters:
242 : /// - [uri]: The image URL as a Uri
243 : /// - [mimeType]: Optional MIME type override
244 : /// - [name]: Optional custom display name
245 : /// - [size]: Optional image size
246 0 : ImageNetworkMedia(
247 : Uri uri, {
248 : super.mimeType,
249 : super.name,
250 : super.size,
251 0 : }) : super._(
252 : uri: uri,
253 0 : metadata: ImageType(),
254 : );
255 :
256 : /// Creates an [ImageNetworkMedia] from a URL string.
257 : ///
258 : /// Convenience constructor that parses a string URL.
259 : ///
260 : /// Parameters:
261 : /// - [url]: The image URL as a string
262 : /// - [mimeType]: Optional MIME type override
263 : /// - [name]: Optional custom display name
264 : /// - [size]: Optional image size
265 0 : ImageNetworkMedia.url(
266 : String url, {
267 : super.mimeType,
268 : super.name,
269 : super.size,
270 0 : }) : super._(
271 0 : uri: Uri.parse(url),
272 0 : metadata: ImageType(),
273 : );
274 : }
275 :
276 : /// Represents document URLs.
277 : ///
278 : /// Supports documents like PDF, DOC, XLSX, etc. accessible via URL.
279 : /// Supports both Uri and String constructors.
280 : class DocumentNetworkMedia extends NetworkMediaSource<DocumentType> {
281 : /// Creates a [DocumentNetworkMedia] from a Uri object.
282 : ///
283 : /// Parameters:
284 : /// - [uri]: The document URL as a Uri
285 : /// - [mimeType]: Optional MIME type override
286 : /// - [name]: Optional custom display name
287 : /// - [size]: Optional document size
288 0 : @override
289 : DocumentNetworkMedia(
290 : Uri uri, {
291 : super.mimeType,
292 : super.name,
293 : super.size,
294 0 : }) : super._(
295 : uri: uri,
296 0 : metadata: DocumentType(),
297 : );
298 :
299 : /// Creates a [DocumentNetworkMedia] from a URL string.
300 : ///
301 : /// Convenience constructor that parses a string URL.
302 : ///
303 : /// Parameters:
304 : /// - [url]: The document URL as a string
305 : /// - [mimeType]: Optional MIME type override
306 : /// - [name]: Optional custom display name
307 : /// - [size]: Optional document size
308 0 : DocumentNetworkMedia.url(
309 : String url, {
310 : super.mimeType,
311 : super.name,
312 : super.size,
313 0 : }) : super._(
314 0 : uri: Uri.parse(url),
315 0 : metadata: DocumentType(),
316 : );
317 : }
318 :
319 : /// Represents URLs for media types that don't fit standard categories.
320 : ///
321 : /// Used for unclassified or unsupported network media types.
322 : class UnSupportedNetworkMedia extends NetworkMediaSource<OtherType> {
323 : /// Creates an [UnSupportedNetworkMedia] from a Uri object.
324 : ///
325 : /// Parameters:
326 : /// - [uri]: The media URL as a Uri
327 : /// - [mimeType]: Optional MIME type override
328 : /// - [name]: Optional custom display name
329 : /// - [size]: Optional media size
330 0 : @override
331 : UnSupportedNetworkMedia(Uri uri, {super.mimeType, super.name, super.size})
332 0 : : super._(
333 : uri: uri,
334 0 : metadata: OtherType(),
335 : );
336 : }
337 :
338 : /// Represents a generic URL, separate from media classification.
339 : ///
340 : /// Used for any URL that needs to be stored as metadata without
341 : /// media type classification. Unlike other network media sources,
342 : /// this represents the URL itself as the primary resource.
343 : class UrlMedia extends NetworkMediaSource<UrlType> {
344 : /// Creates a [UrlMedia] from a Uri object.
345 : ///
346 : /// Parameters:
347 : /// - [uri]: The URL as a Uri object
348 0 : UrlMedia(Uri uri)
349 0 : : super._(
350 0 : size: 0.b,
351 : mimeType: 'url',
352 0 : metadata: UrlType(),
353 : uri: uri,
354 : );
355 :
356 : /// Creates a [UrlMedia] from a URL string.
357 : ///
358 : /// Convenience constructor that parses a string URL.
359 : ///
360 : /// Parameters:
361 : /// - [url]: The URL as a string
362 0 : UrlMedia.url(String url) : this(Uri.parse(url));
363 :
364 : /// Includes only URI and metadata for equality comparisons.
365 0 : @override
366 0 : List<Object?> get props => [uri, metadata];
367 : }
|