Player constructor
Player()
Implementation
Player() {
_pp.value = _player;
_receivePort.listen((message) async {
final type = message[0] as int;
final rep = calloc<_CallbackReply>();
switch (type) {
case 0:
{
// event
final error = message[1] as int;
final category = message[2] as String;
final detail = message[3] as String;
final ev = MediaEvent(error, category, detail);
for (final cb in _eventCb) {
cb(ev);
}
}
case 1:
{
// state
final oldValue = message[1] as int;
final newValue = message[2] as int;
for (final cb in _stateCb) {
cb(PlaybackState.from(oldValue), PlaybackState.from(newValue));
}
Libfvp.replyType(nativeHandle, type, nullptr);
}
case 2:
{
// media status
final oldValue = message[1] as int;
final newValue = message[2] as int;
bool ret = true;
for (var cb in _statusCb) {
ret = cb(MediaStatus(oldValue), MediaStatus(newValue)) && ret;
}
rep.ref.mediaStatus.ret = ret;
Libfvp.replyType(nativeHandle, type, rep.cast());
}
case 3:
{
// prepared
final pos = message[1] as int;
_live = message[2] as bool;
if (!_prepared.isCompleted) {
_prepared.complete(pos);
}
rep.ref.prepared.ret = true;
rep.ref.prepared.boost = true;
/*
// callback can be late if prepare from pos > 0
if (_videoSize.isCompleted)
_videoSize = Completer<ui.Size?>();
if (!_videoSize.isCompleted) {
if (pos < 0) {
_videoSize.complete(null);
} else {
_setVideoSize();
}
}*/
if (_prepareCb != null) {
rep.ref.prepared.ret = await _prepareCb!();
_prepareCb = null;
}
Libfvp.replyType(nativeHandle, type, rep.cast());
}
case 6:
{
// seek
final pos = message[1] as int;
if (!(_seeked?.isCompleted ?? true)) {
_seeked?.complete(pos);
}
_seeked = null;
}
case 7:
{
final data = message[1] as Uint8List; //null?
if (!(_snapshot?.isCompleted ?? true)) {
_snapshot?.complete(data.isEmpty ? null : data);
}
_snapshot = null;
}
}
calloc.free(rep);
});
Libfvp.registerPort(nativeHandle, NativeApi.postCObject.cast(),
_receivePort.sendPort.nativePort);
onStateChanged((oldValue, newValue) {
_state = newValue;
});
onMediaStatus((oldValue, newValue) {
if (!oldValue.test(MediaStatus.loaded) &&
newValue.test(MediaStatus.loaded)) {
_setVideoSize();
}
if (!oldValue.test(MediaStatus.loading) &&
newValue.test(MediaStatus.loading)) {
if (_videoSize.isCompleted) {
// updateTexture() may be awaiting and won't wake up if reset to a new object here
_videoSize = Completer<ui.Size?>();
}
}
if (oldValue.test(MediaStatus.loading) &&
newValue.test(MediaStatus.invalid | MediaStatus.stalled)) {
_videoSize.complete(null);
}
if (oldValue.test(MediaStatus.loaded) &&
!newValue.test(MediaStatus.loaded)) {
// invalid mediaInfo when loaded(small probe size, bad format etc.), then failed to decode
if (!_videoSize.isCompleted) {
_videoSize.complete(null);
}
}
return true;
});
onEvent((e) {
if (_videoSize.isCompleted) {
return;
}
if (e.category == 'decoder.video') {
_setVideoSize();
}
});
}