Skip to content

Commit

Permalink
Add :start-time & :stop-time handling & factory const. in Media
Browse files Browse the repository at this point in the history
  • Loading branch information
alexmercerind committed Sep 29, 2021
1 parent 7191cb7 commit 65a17d2
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 42 deletions.
88 changes: 66 additions & 22 deletions ffi/lib/src/mediaSource/media.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,56 +16,87 @@ import 'package:dart_vlc_ffi/src/enums/mediaType.dart';
/// * A [Media] from a [File].
///
/// ```dart
/// Media media = await Media.file(new File('C:/music.ogg'));
/// Media media = Media.file(File('C:/music.ogg'));
/// ```
///
/// * A [Media] from a [Uri].
///
/// ```dart
/// Media media = await Media.network('http://alexmercerind.github.io/music.mp3');
/// Media media = Media.network('http://alexmercerind.github.io/music.mp3');
/// ```
///
/// For starting a [Media] at particular time, one can pass `startTime`.
///
/// ```dart
/// Media media = Media.file(
/// File('C:/music.ogg'),
/// startTime: Duration(milliseconds: 20),
/// );
/// ```
///
class Media implements MediaSource {
MediaSourceType get mediaSourceType => MediaSourceType.media;
final MediaType mediaType;
final String resource;
final Duration startTime;
final Duration stopTime;
final Map<String, String> metas;

const Media._(
{required this.mediaType, required this.resource, required this.metas});
const Media._({
required this.mediaType,
required this.resource,
required this.metas,
this.startTime: Duration.zero,
this.stopTime: Duration.zero,
});

/// Makes [Media] object from a [File].
static Media file(File file,
{bool parse: false,
Map<String, dynamic>? extras,
Duration timeout: const Duration(seconds: 10)}) {
final media =
Media._(mediaType: MediaType.file, resource: file.path, metas: {});

factory Media.file(
File file, {
bool parse: false,
Map<String, dynamic>? extras,
Duration timeout: const Duration(seconds: 10),
startTime: Duration.zero,
stopTime: Duration.zero,
}) {
final media = Media._(
mediaType: MediaType.file,
resource: file.path,
metas: {},
startTime: startTime,
stopTime: stopTime,
);
if (parse) {
media.parse(timeout);
}
return media;
}

/// Makes [Media] object from url.
static Media network(dynamic url,
{bool parse: false,
Map<String, dynamic>? extras,
Duration timeout: const Duration(seconds: 10)}) {
factory Media.network(
dynamic url, {
bool parse: false,
Map<String, dynamic>? extras,
Duration timeout: const Duration(seconds: 10),
startTime: Duration.zero,
stopTime: Duration.zero,
}) {
final resource = (url is Uri) ? url.toString() : url;
final Media media =
Media._(mediaType: MediaType.network, resource: resource, metas: {});

final Media media = Media._(
mediaType: MediaType.network,
resource: resource,
metas: {},
startTime: startTime,
stopTime: stopTime,
);
if (parse) {
media.parse(timeout);
}
return media;
}

/// Makes [Media] object from direct show.
static Media directShow(
factory Media.directShow(
{String? rawUrl,
Map<String, dynamic>? args,
String? vdev,
Expand All @@ -90,7 +121,10 @@ class Media implements MediaSource {
/// This method only works for Flutter.
/// Might result in an exception on Dart CLI.
///
static Media asset(String asset) {
factory Media.asset(
String asset, {
startTime: Duration.zero,
}) {
String? assetPath;
if (Platform.isWindows || Platform.isLinux) {
assetPath = path.join(
Expand Down Expand Up @@ -119,12 +153,16 @@ class Media implements MediaSource {
);
}
if (assetPath == null) {
// TODO: Add Android asset path support.
// TODO: Add Android support.
throw UnimplementedError('The platform is not supported');
}
final url = Uri.file(assetPath, windows: Platform.isWindows);
return Media._(
mediaType: MediaType.asset, resource: url.toString(), metas: {});
mediaType: MediaType.asset,
resource: url.toString(),
metas: {},
startTime: startTime,
);
}

/// Parses the [Media] to retrieve [Media.metas].
Expand Down Expand Up @@ -181,3 +219,9 @@ class Media implements MediaSource {
@override
String toString() => '[$mediaType]$resource';
}

extension DurationExtension on Duration {
String argument(String value) => this == Duration.zero
? ''
: ':$value=${(inMilliseconds / 1000).toStringAsFixed(6)}';
}
95 changes: 75 additions & 20 deletions ffi/lib/src/player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -154,18 +154,33 @@ class Player {
PlayerFFI.open(
this.id,
autoStart ? 1 : 0,
<String>[source.mediaType.toString(), source.resource]
.toNativeUtf8Array(),
<String>[
source.mediaType.toString(),
source.resource,
source.startTime.argument('start-time'),
source.stopTime.argument('stop-time'),
].toNativeUtf8Array(),
1);
}
if (source is Playlist) {
List<String> medias = <String>[];
source.medias.forEach((media) {
medias.add(media.mediaType.toString());
medias.add(media.resource);
medias.addAll(
<String>[
media.mediaType.toString(),
media.resource,
media.startTime.argument('start-time'),
media.stopTime.argument('stop-time'),
],
);
});
PlayerFFI.open(this.id, autoStart ? 1 : 0, medias.toNativeUtf8Array(),
source.medias.length);
print(medias);
PlayerFFI.open(
this.id,
autoStart ? 1 : 0,
medias.toNativeUtf8Array(),
source.medias.length,
);
}
}

Expand Down Expand Up @@ -206,54 +221,86 @@ class Player {
/// Jumps to [Media] at specific index in the [Playlist] opened.
/// Pass index as parameter.
void jump(int index) {
PlayerFFI.jump(this.id, index);
PlayerFFI.jump(
this.id,
index,
);
}

/// Seeks the [Media] currently playing in the [Player] instance, to the provided [Duration].
void seek(Duration duration) {
PlayerFFI.seek(this.id, duration.inMilliseconds);
PlayerFFI.seek(
this.id,
duration.inMilliseconds,
);
}

/// Sets volume of the [Player] instance.
void setVolume(double volume) {
PlayerFFI.setVolume(this.id, volume);
PlayerFFI.setVolume(
this.id,
volume,
);
}

/// Sets playback rate of the [Media] currently playing in the [Player] instance.
void setRate(double rate) {
PlayerFFI.setRate(this.id, rate);
PlayerFFI.setRate(
this.id,
rate,
);
}

/// Sets user agent for dart_vlc player.
void setUserAgent(String userAgent) {
PlayerFFI.setUserAgent(this.id, userAgent.toNativeUtf8());
PlayerFFI.setUserAgent(
this.id,
userAgent.toNativeUtf8(),
);
}

/// Changes [Playlist] playback mode.
void setPlaylistMode(PlaylistMode playlistMode) {
PlayerFFI.setPlaylistMode(this.id, playlistMode.toString().toNativeUtf8());
PlayerFFI.setPlaylistMode(
this.id,
playlistMode.toString().toNativeUtf8(),
);
}

/// Appends [Media] to the [Playlist] of the [Player] instance.
void add(Media source) {
PlayerFFI.add(this.id, source.mediaType.toString().toNativeUtf8(),
source.resource.toString().toNativeUtf8());
PlayerFFI.add(
this.id,
source.mediaType.toString().toNativeUtf8(),
source.resource.toString().toNativeUtf8(),
);
}

/// Removes [Media] from the [Playlist] at a specific index.
void remove(int index) {
PlayerFFI.remove(this.id, index);
PlayerFFI.remove(
this.id,
index,
);
}

/// Inserts [Media] to the [Playlist] of the [Player] instance at specific index.
void insert(int index, Media source) {
PlayerFFI.insert(this.id, index, source.mediaType.toString().toNativeUtf8(),
source.resource.toString().toNativeUtf8());
PlayerFFI.insert(
this.id,
index,
source.mediaType.toString().toNativeUtf8(),
source.resource.toString().toNativeUtf8(),
);
}

/// Moves [Media] already present in the [Playlist] of the [Player] from [initialIndex] to [finalIndex].
void move(int initialIndex, int finalIndex) {
PlayerFFI.move(this.id, initialIndex, finalIndex);
PlayerFFI.move(
this.id,
initialIndex,
finalIndex,
);
}

/// Sets playback [Device] for the instance of [Player].
Expand All @@ -265,7 +312,10 @@ class Player {
///
void setDevice(Device device) {
PlayerFFI.setDevice(
this.id, device.id.toNativeUtf8(), device.name.toNativeUtf8());
this.id,
device.id.toNativeUtf8(),
device.name.toNativeUtf8(),
);
}

/// Sets [Equalizer] for the [Player].
Expand All @@ -275,7 +325,12 @@ class Player {

/// Saves snapshot of a video to a desired [File] location.
void takeSnapshot(File file, int width, int height) {
PlayerFFI.takeSnapshot(this.id, file.path.toNativeUtf8(), width, height);
PlayerFFI.takeSnapshot(
this.id,
file.path.toNativeUtf8(),
width,
height,
);
}

/// Destroys the instance of [Player] & closes all [StreamController]s in it.
Expand Down

0 comments on commit 65a17d2

Please sign in to comment.