Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/video_player/video_player_web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 0.1.0

* Initial release
27 changes: 27 additions & 0 deletions packages/video_player/video_player_web/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 changes: 25 additions & 0 deletions packages/video_player/video_player_web/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# video_player_web

The web implementation of [`video_player`][1].

## Usage

To use this plugin in your Flutter Web app, simply add it as a dependency in
your pubspec using a `git` dependency. This is only temporary: in the future
we hope to make this package an "endorsed" implementation of `video_player`,
so that it is automatically included in your Flutter Web app when you depend
on `package:video_player`.

```yaml
dependencies:
video_player: ^0.10.4
video_player_web:
git:
url: git://github.com/flutter/plugins.git
path: packages/video_player/video_player_web
```

Once you have the `video_player_web` dependency in your pubspec, you should
be able to use `package:video_player` as normal.

[1]: ../video_player
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
s.name = 'video_player_web'
s.version = '0.0.1'
s.summary = 'No-op implementation of video_player_web web plugin to avoid build issues on iOS'
s.description = <<-DESC
temp fake video_player_web plugin
DESC
s.homepage = 'https://github.com/flutter/plugins/tree/master/packages/video_player/video_player_web'
s.license = { :file => '../LICENSE' }
s.author = { 'Flutter Team' => 'flutter-dev@googlegroups.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'

s.ios.deployment_target = '8.0'
end
196 changes: 196 additions & 0 deletions packages/video_player/video_player_web/lib/video_player_web.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
import 'dart:async';
import 'dart:html';
import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:video_player_platform_interface/video_player_platform_interface.dart';

/// The web implementation of [VideoPlayerPlatform].
///
/// This class implements the `package:video_player` functionality for the web.
class VideoPlayerPlugin extends VideoPlayerPlatform {
/// Registers this class as the default instance of [VideoPlayerPlatform].
static void registerWith(Registrar registrar) {
VideoPlayerPlatform.instance = VideoPlayerPlugin();
}

Map<int, _VideoPlayer> _videoPlayers = <int, _VideoPlayer>{};

int _textureCounter = 1;

@override
Future<void> init() async {
return _disposeAllPlayers();
}

@override
Future<void> dispose(int textureId) async {
_videoPlayers[textureId].dispose();
_videoPlayers.remove(textureId);
return null;
}

void _disposeAllPlayers() {
_videoPlayers.values
.forEach((_VideoPlayer videoPlayer) => videoPlayer.dispose());
_videoPlayers.clear();
}

@override
Future<int> create(DataSource dataSource) async {
final int textureId = _textureCounter;
_textureCounter++;

final _VideoPlayer player = _VideoPlayer(
uri: Uri.parse(dataSource.uri),
textureId: textureId,
);

player.setupVideoPlayer();

_videoPlayers[textureId] = player;
return textureId;
}

@override
Future<void> setLooping(int textureId, bool looping) async {
return _videoPlayers[textureId].setLooping(looping);
}

@override
Future<void> play(int textureId) async {
return _videoPlayers[textureId].play();
}

@override
Future<void> pause(int textureId) async {
return _videoPlayers[textureId].pause();
}

@override
Future<void> setVolume(int textureId, double volume) async {
return _videoPlayers[textureId].setVolume(volume);
}

@override
Future<void> seekTo(int textureId, Duration position) async {
return _videoPlayers[textureId].seekTo(position);
}

@override
Future<Duration> getPosition(int textureId) async {
_videoPlayers[textureId].sendBufferingUpdate();
return _videoPlayers[textureId].getPosition();
}

@override
Stream<VideoEvent> videoEventsFor(int textureId) {
return _videoPlayers[textureId].eventController.stream;
}

@override
Widget buildView(int textureId) {
return HtmlElementView(viewType: 'videoPlayer-$textureId');
}
}

class _VideoPlayer {
_VideoPlayer({this.uri, this.textureId});

final StreamController<VideoEvent> eventController =
StreamController<VideoEvent>();

final Uri uri;
final int textureId;
VideoElement videoElement;
bool isInitialized = false;

void setupVideoPlayer() {
videoElement = VideoElement()
..src = uri.toString()
..autoplay = false
..controls = false
..style.border = 'none';

// TODO(hterkelsen): Use initialization parameters once they are available
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
'videoPlayer-$textureId', (int viewId) => videoElement);

videoElement.onCanPlay.listen((dynamic _) {
if (!isInitialized) {
isInitialized = true;
sendInitialized();
}
});
videoElement.onError.listen((dynamic error) {
eventController.addError(error);
});
videoElement.onEnded.listen((dynamic _) {
eventController.add(VideoEvent(eventType: VideoEventType.completed));
});
}

void sendBufferingUpdate() {
eventController.add(VideoEvent(
buffered: _toDurationRange(videoElement.buffered),
eventType: VideoEventType.completed,
));
}

void play() {
videoElement.play();
}

void pause() {
videoElement.pause();
}

void setLooping(bool value) {
videoElement.loop = value;
}

void setVolume(double value) {
videoElement.volume = value;
}

void seekTo(Duration position) {
videoElement.currentTime = position.inMilliseconds.toDouble() / 1000;
}

Duration getPosition() {
return Duration(milliseconds: (videoElement.currentTime * 1000).round());
}

void sendInitialized() {
eventController.add(
VideoEvent(
eventType: VideoEventType.initialized,
duration: Duration(
milliseconds: (videoElement.duration * 1000).round(),
),
size: Size(
videoElement.videoWidth.toDouble() ?? 0.0,
videoElement.videoHeight.toDouble() ?? 0.0,
),
),
);
}

void dispose() {
videoElement.removeAttribute('src');
videoElement.load();
}

List<DurationRange> _toDurationRange(TimeRanges buffered) {
final List<DurationRange> durationRange = <DurationRange>[];
for (int i = 0; i < buffered.length; i++) {
durationRange.add(DurationRange(
Duration(milliseconds: (buffered.start(i) * 1000).round()),
Duration(milliseconds: (buffered.end(i) * 1000).round()),
));
}
return durationRange;
}
}
30 changes: 30 additions & 0 deletions packages/video_player/video_player_web/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: video_player_web
description: Web platform implementation of video_player
author: Flutter Team <flutter-dev@googlegroups.com>
homepage: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player_web
version: 0.1.0

flutter:
plugin:
platforms:
web:
pluginClass: VideoPlayerPlugin
fileName: video_player_web.dart

dependencies:
flutter:
sdk: flutter
flutter_web_plugins:
sdk: flutter
meta: ^1.1.7
video_player_platform_interface: ^1.0.0

dev_dependencies:
flutter_test:
sdk: flutter
video_player:
path: ../video_player

environment:
sdk: ">=2.0.0-dev.28.0 <3.0.0"
flutter: ">=1.5.0 <2.0.0"
Loading