[cleanup] remove examples/mediaplayer/*
Removes old mediaplayer example and remaining, unused dependencies:
- public/lib/mediaplayer/dart
- public/lib/mediaplayer/flutter
Integration verified with:
fx make-integration-patch
Change-Id: I90cb9acd21696634f5184ca3ca7cb3d71864430e
Reviewed-on: https://fuchsia-review.googlesource.com/c/topaz/+/376153
Reviewed-by: Chase Latta <chaselatta@google.com>
Reviewed-by: Dale Sather <dalesat@google.com>
Commit-Queue: Jason Campbell <jasoncampbell@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 92fdbb2..51d3179 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -10,7 +10,6 @@
"//topaz/bin/fidlgen_dart:install(//build/toolchain:host_x64)",
"//topaz/examples/fidl/echo_client_async_dart",
"//topaz/examples/fidl/echo_server_async_dart",
- "//topaz/examples/mediaplayer/mediaplayer_flutter",
"//topaz/examples/ui/button_flutter",
"//topaz/lib/story_shell/examples/example_manual_relationships",
"//topaz/public/dart/fuchsia_inspect/codelab:bin",
diff --git a/examples/mediaplayer/OWNERS b/examples/mediaplayer/OWNERS
deleted file mode 100644
index dcc89ec..0000000
--- a/examples/mediaplayer/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-dalesat@google.com
-*
diff --git a/examples/mediaplayer/mediaplayer_flutter/BUILD.gn b/examples/mediaplayer/mediaplayer_flutter/BUILD.gn
deleted file mode 100644
index 5f8fe51..0000000
--- a/examples/mediaplayer/mediaplayer_flutter/BUILD.gn
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2017 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//topaz/runtime/flutter_runner/flutter_app.gni")
-
-flutter_app("mediaplayer_flutter") {
- components = [
- {
- component_name = "mediaplayer_flutter"
- component_type = "flutter"
- package_root = "."
- main_dart = "lib/main.dart"
- sources = [
- "asset.dart",
- "config.dart",
- ]
- deps = [
- "//sdk/fidl/fuchsia.modular",
- "//third_party/dart-pkg/git/flutter/packages/flutter",
- "//topaz/public/dart/fidl",
- "//topaz/public/dart/fuchsia",
- "//topaz/public/dart/fuchsia_logger",
- "//topaz/public/dart/fuchsia_modular",
- "//topaz/public/dart/fuchsia_services",
- "//topaz/public/lib/mediaplayer/flutter",
- ]
- },
- ]
-
- meta = [
- {
- path = rebase_path("meta/mediaplayer_flutter.cmx")
- dest = "mediaplayer_flutter.cmx"
- },
- ]
-
- resources = [
- {
- path = rebase_path("mediaplayer_flutter.config")
- dest = "mediaplayer_flutter.config"
- },
- ]
-}
diff --git a/examples/mediaplayer/mediaplayer_flutter/README.md b/examples/mediaplayer/mediaplayer_flutter/README.md
deleted file mode 100644
index 9788b34..0000000
--- a/examples/mediaplayer/mediaplayer_flutter/README.md
+++ /dev/null
@@ -1,101 +0,0 @@
-# Flutter-based Media Player Example App
-
-This directory contains an application that uses media and Flutter to
-create a media player.
-
-## USAGE
-
-Run the app as follows:
-
- present_view mediaplayer_flutter
-
-The initial screen is a menu of content items that can be played, unless the
-config file contains only one asset, in which case the chooser screen is
-skipped. Touch one of the items to play it. Note that the default config file
-contains only one item.
-
-The app will look for config files in two places, reading only the first file
-it finds:
-
-- /data/mediaplayer_flutter.config
-- /pkg/data/mediaplayer_flutter.config
-
-Here's an example config file:
-
- [
- {
- "uri": "http://192.168.4.1/big_buck_bunny.ogv",
- "title": "Big Buck Bunny"
- },
- {
- "uri": "http://192.168.4.1/policehelicopter.ogg",
- "title": "Police Helicopter",
- "artist": "The Red Hot Chili Peppers",
- "album": "The Red Hot Chili Peppers",
- "loop": "true"
- },
- {
- "uri": "http://192.168.4.1/superstition.ogg",
- "title": "Superstition",
- "artist": "Stevie Wonder",
- "album": "At the Close of the Century Disc 2"
- },
- {
- "title": "Both Songs",
- "children": [
- {
- "uri": "http://192.168.4.1/policehelicopter.ogg",
- "title": "Police Helicopter",
- "artist": "The Red Hot Chili Peppers",
- "album": "The Red Hot Chili Peppers"
- },
- {
- "uri": "http://192.168.4.1/superstition.ogg",
- "title": "Superstition",
- "artist": "Stevie Wonder",
- "album": "At the Close of the Century Disc 2"
- }
- ]
- }
- ]
-
-The config file must be well-formed JSON specifying an array of objects. An
-object describes a movie, a song or a playlist of movies and songs.
-
-The following object fields are supported:
-
-### uri (or url)
-
-Specifies the URI from which to obtain the content. The file scheme is
-supported for files on the device. This field is required for movies and songs
-and prohibited for playlists.
-
-### children
-
-Specifies an array of items to populate this item, which must be a playlist.
-This field is required for playlists and prohibited for all other item types.
-
-### type
-
-Specifies the type of the item, one of "movie", "music" or "playlist".
-This field is optional. If it's absent, the app will attempt to infer the type
-of the content.
-
-### title
-
-The title of the item. This field is optional. If it's absent, the item will be
-titled "(untitled)" in the content chooser. During playback, the app will
-attempt to get the title from the content, if applicable.
-
-### artist
-
-The name of the artist who created the content. This field is optional.
-
-### album
-
-The name of the album on which the content appears. This field is optional.
-
-### loop
-
-Whether the item should be looped. This field is optional. Playlists can be
-looped.
diff --git a/examples/mediaplayer/mediaplayer_flutter/analysis_options.yaml b/examples/mediaplayer/mediaplayer_flutter/analysis_options.yaml
deleted file mode 100644
index 7415796..0000000
--- a/examples/mediaplayer/mediaplayer_flutter/analysis_options.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2017 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-include: ../../../tools/analysis_options.yaml
diff --git a/examples/mediaplayer/mediaplayer_flutter/lib/asset.dart b/examples/mediaplayer/mediaplayer_flutter/lib/asset.dart
deleted file mode 100644
index 3f8a750..0000000
--- a/examples/mediaplayer/mediaplayer_flutter/lib/asset.dart
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'package:meta/meta.dart';
-
-/// The asset types.
-enum AssetType {
- /// Individual assets containing both audio and video.
- movie,
-
- /// Individual assets containing only audio.
- song,
-
- /// Composite assets that consist of a list of other assets.
- playlist,
-}
-
-/// Describes an asset.
-class Asset {
- /// Uri of the asset. Must be null for playlists, required for
- /// all other asset types.
- final Uri uri;
-
- /// Type of the asset.
- final AssetType type;
-
- /// Title of the asset. May be null.
- final String title;
-
- /// Artist to which the asset is attributed. May be null.
- final String artist;
-
- /// Album name for the asset. May be null.
- final String album;
-
- /// Children of the playlist asset. Must be null for other asset types.
- final List<Asset> children;
-
- /// Whether the asset should loop back to the beginning when it ends.
- final bool loop;
-
- /// Constructs an asset describing a movie.
- Asset.movie({
- @required this.uri,
- this.title,
- this.artist,
- this.album,
- this.loop,
- }) : type = AssetType.movie,
- children = null;
-
- /// Constructs an asset describing a song.
- Asset.song({
- @required this.uri,
- this.title,
- this.artist,
- this.album,
- this.loop,
- }) : type = AssetType.song,
- children = null;
-
- /// Constructs an asset describing a playlist.
- Asset.playlist({
- @required this.children,
- this.title,
- this.loop,
- }) : assert(children.isNotEmpty),
- type = AssetType.playlist,
- uri = null,
- artist = null,
- album = null {
- assert(children.every(
- (Asset c) => c.type == AssetType.movie || c.type == AssetType.song));
- }
-}
diff --git a/examples/mediaplayer/mediaplayer_flutter/lib/config.dart b/examples/mediaplayer/mediaplayer_flutter/lib/config.dart
deleted file mode 100644
index 0b34451..0000000
--- a/examples/mediaplayer/mediaplayer_flutter/lib/config.dart
+++ /dev/null
@@ -1,229 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io';
-
-import 'asset.dart';
-
-/// Reads the configuration from [fileName].
-Future<List<Asset>> readConfig(String fileName) async {
- File file = File(fileName);
-
- if (!file.existsSync()) {
- throw ArgumentError.value(fileName, 'fileName', 'File does not exist');
- }
-
- return _convertAssetList(json.decode(await file.readAsString()));
-}
-
-String _convertString(Object json) {
- if (json is! String) {
- throw const FormatException('Config file is malformed: string expected');
- }
-
- return json;
-}
-
-bool _convertBool(Object json) {
- if (json is! String || (json != 'true' && json != 'false')) {
- throw const FormatException(
- 'Config file is malformed: "true" or "false" expected');
- }
-
- return json == 'true';
-}
-
-Asset _convertAsset(Object json) {
- if (json is! Map) {
- throw const FormatException('Config file is malformed: object expected');
- }
-
- Map<String, Object> jsonMap = json;
-
- Uri uri;
- AssetType type;
- String title;
- String artist;
- String album;
- List<Asset> children;
- bool loop = false;
-
- jsonMap.forEach((String key, Object value) {
- switch (key) {
- case 'uri':
- case 'url':
- try {
- uri = Uri.parse(_convertString(value));
- } on FormatException {
- throw FormatException('Config file is malformed: bad URI $value');
- }
- break;
- case 'type':
- switch (_convertString(value)) {
- case 'movie':
- type = AssetType.movie;
- break;
- case 'song':
- type = AssetType.song;
- break;
- case 'playlist':
- type = AssetType.playlist;
- break;
- default:
- throw FormatException(
- 'Config file is malformed: $value is not a valid type');
- }
- break;
- case 'title':
- title = _convertString(value);
- break;
- case 'artist':
- artist = _convertString(value);
- break;
- case 'album':
- album = _convertString(value);
- break;
- case 'children':
- children = _convertAssetList(value);
- break;
- case 'loop':
- loop = _convertBool(value);
- break;
- }
- });
-
- if (type == null) {
- // Try to infer the type.
- if (uri == null) {
- if (children != null) {
- type = AssetType.playlist;
- }
- } else if (_isMovieUri(uri)) {
- type = AssetType.movie;
- } else if (_isMusicUri(uri)) {
- type = AssetType.song;
- }
- }
-
- if (type == null) {
- throw const FormatException(
- 'Config file is malformed: asset type was not specified and cannot be'
- ' inferred');
- }
-
- switch (type) {
- case AssetType.movie:
- _checkNotNull(type, uri, 'a URI');
- _checkNull(type, children, 'children');
- return Asset.movie(
- uri: uri,
- title: title,
- artist: artist,
- album: album,
- loop: loop,
- );
-
- case AssetType.song:
- _checkNotNull(type, uri, 'a URI');
- _checkNull(type, children, 'children');
- return Asset.song(
- uri: uri,
- title: title,
- artist: artist,
- album: album,
- loop: loop,
- );
-
- case AssetType.playlist:
- _checkNull(type, uri, 'a URI');
- _checkNotNull(type, children, 'children');
- _checkNull(type, artist, 'artist name');
- _checkNull(type, album, 'album name');
- if (children.isEmpty) {
- throw const FormatException(
- 'Config file is malformed: a playlist must have at least one child');
- }
- if (!children.every(
- (Asset c) => c.type == AssetType.movie || c.type == AssetType.song)) {
- throw const FormatException(
- 'Config file is malformed: playlist children must be songs or movies');
- }
- return Asset.playlist(
- title: title,
- children: children,
- loop: loop,
- );
-
- default:
- throw FormatException('Unknown asset type: $type');
- }
-}
-
-void _checkNotNull(AssetType type, Object value, String name) {
- if (value == null) {
- throw FormatException(
- 'Config file is malformed: a $type must have $name');
- }
-}
-
-void _checkNull(AssetType type, Object value, String name) {
- if (value != null) {
- throw FormatException(
- 'Config file is malformed: a $type must not have $name');
- }
-}
-
-List<Asset> _convertAssetList(Object json) {
- if (json is! List) {
- throw const FormatException('Config file is malformed: array expected');
- }
-
- List<Object> jsonList = json;
-
- List<Asset> list = <Asset>[];
-
- for (Object item in jsonList) {
- Asset asset = _convertAsset(item);
- if (asset != null) {
- list.add(asset);
- }
- }
-
- return list;
-}
-
-bool _isMovieUri(Uri uri) {
- switch (_extension(uri)) {
- case 'ogv':
- case 'mp4':
- case 'vp8':
- case 'vp9':
- case 'mkv':
- case 'mov':
- case 'webm':
- return true;
- }
-
- return false;
-}
-
-bool _isMusicUri(Uri uri) {
- switch (_extension(uri)) {
- case 'ogg':
- case 'wav':
- case 'mp3':
- case 'flac':
- return true;
- }
-
- return false;
-}
-
-String _extension(Uri uri) {
- String lastSegment = uri.pathSegments.last;
- int index = lastSegment.lastIndexOf('.');
- return index == -1 ? null : lastSegment.substring(index + 1);
-}
diff --git a/examples/mediaplayer/mediaplayer_flutter/lib/main.dart b/examples/mediaplayer/mediaplayer_flutter/lib/main.dart
deleted file mode 100644
index 167a7c8..0000000
--- a/examples/mediaplayer/mediaplayer_flutter/lib/main.dart
+++ /dev/null
@@ -1,387 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:io' as io;
-
-import 'package:fidl_fuchsia_media/fidl_async.dart' as media;
-import 'package:fidl_fuchsia_media_playback/fidl_async.dart' as playback;
-import 'package:flutter/material.dart';
-import 'package:flutter/widgets.dart';
-import 'package:fuchsia_logger/logger.dart';
-import 'package:fuchsia_modular/module.dart';
-import 'package:fuchsia_services/services.dart';
-import 'package:lib.mediaplayer.flutter/media_player.dart';
-import 'package:lib.mediaplayer.flutter/media_player_controller.dart';
-
-import 'asset.dart';
-import 'config.dart';
-
-final _context = StartupContext.fromStartupInfo();
-final MediaPlayerController _controller =
- MediaPlayerController(_context.incoming);
-
-const List<String> _configFileNames = <String>[
- '/data/mediaplayer_flutter.config',
- '/pkg/data/mediaplayer_flutter.config',
-];
-
-List<Asset> _assets = <Asset>[];
-Asset _assetToPlay;
-Asset _leafAssetToPlay;
-int _playlistIndex;
-
-Future<Null> _readConfig() async {
- for (String fileName in _configFileNames) {
- try {
- _assets = await readConfig(fileName);
- return;
- // ignore: avoid_catching_errors
- } on ArgumentError {
- // File doesn't exist. Continue.
- } on FormatException catch (e) {
- print('Failed to parse config $fileName: $e');
- io.exit(0);
- return;
- }
- }
-
- print('No config file found');
- io.exit(0);
-}
-
-/// Plays the specified asset.
-void _play(Asset asset) {
- assert(asset != null);
-
- _assetToPlay = asset;
- _playlistIndex = 0;
-
- if (_assetToPlay.children != null) {
- assert(_assetToPlay.children.isNotEmpty);
- _playLeafAsset(_assetToPlay.children[0]);
- } else {
- _playLeafAsset(_assetToPlay);
- }
-}
-
-/// If [_leafAssetToPlay] is looped, this method seeks to the beginning of the
-/// asset and returns true. If [_assetToPlay] is a playlist and hasn't been
-/// played through (or is looped), this method plays the next asset in
-/// [_assetToPlay] and returns true. Returns false otherwise.
-bool _playNext() {
- if (_leafAssetToPlay.loop) {
- // Looping leaf asset. Seek to the beginning.
- _controller.seek(Duration.zero);
- return true;
- }
-
- if (_assetToPlay == null || _assetToPlay.children == null) {
- return false;
- }
-
- if (_assetToPlay.children.length <= ++_playlistIndex) {
- if (!_assetToPlay.loop) {
- return false;
- }
-
- // Looping playlist. Start over.
- _playlistIndex = 0;
- }
-
- _playLeafAsset(_assetToPlay.children[_playlistIndex]);
-
- return true;
-}
-
-void _playLeafAsset(Asset asset) {
- assert(asset.type != AssetType.playlist);
-
- _leafAssetToPlay = asset;
-
- if (_controller.problem?.type == playback.problemConnectionFailed) {
- _controller.close();
- }
-
- _controller
- ..open(_leafAssetToPlay.uri)
- ..play();
-}
-
-/// Screen for asset playback.
-class _PlaybackScreen extends StatefulWidget {
- const _PlaybackScreen({Key key}) : super(key: key);
-
- @override
- _PlaybackScreenState createState() => _PlaybackScreenState();
-}
-
-class _PlaybackScreenState extends State<_PlaybackScreen> {
- @override
- void initState() {
- _controller.addListener(_handleControllerChanged);
- super.initState();
- }
-
- @override
- void dispose() {
- _controller.removeListener(_handleControllerChanged);
- super.dispose();
- }
-
- /// Handles change notifications from the controller.
- void _handleControllerChanged() {
- setState(() {
- if (_controller.ended) {
- _playNext();
- }
- });
- }
-
- /// Adds a label to list [to] if [label] isn't null.
- void _addLabel(String label, Color color, double fontSize, List<Widget> to) {
- if (label == null) {
- return;
- }
-
- to.add(Container(
- margin: EdgeInsets.only(left: 10.0),
- child: Text(
- label,
- style: TextStyle(color: color, fontSize: fontSize),
- ),
- ));
- }
-
- /// Adds a problem description to list [to] if there is a problem.
- void _addProblem(List<Widget> to) {
- playback.Problem problem = _controller.problem;
- if (problem != null) {
- String text;
-
- if (problem.details != null && problem.details.isNotEmpty) {
- text = problem.details;
- } else {
- switch (problem.type) {
- case playback.problemInternal:
- text = 'Internal error';
- break;
- case playback.problemAssetNotFound:
- text = 'The requested content was not found';
- break;
- case playback.problemContainerNotSupported:
- text = 'The requested content uses an unsupported container format';
- break;
- case playback.problemAudioEncodingNotSupported:
- text = 'The requested content uses an unsupported audio encoding';
- break;
- case playback.problemVideoEncodingNotSupported:
- text = 'The requested content uses an unsupported video encoding';
- break;
- case playback.problemConnectionFailed:
- text = 'Connection to player failed';
- break;
- default:
- text = 'Unrecognized problem type ${problem.type}';
- break;
- }
- }
-
- _addLabel(text, Colors.white, 20.0, to);
-
- if (_leafAssetToPlay != null && _leafAssetToPlay.uri != null) {
- _addLabel(_leafAssetToPlay.uri.toString(), Colors.grey[800], 15.0, to);
- }
- }
- }
-
- @override
- Widget build(BuildContext context) {
- List<Widget> columnChildren = <Widget>[
- MediaPlayer(_controller),
- ];
-
- Map<String, String> metadata = _controller.metadata;
- if (metadata != null) {
- _addLabel(
- metadata[media.metadataLabelTitle] ??
- _leafAssetToPlay.title ??
- '(untitled)',
- Colors.white,
- 20.0,
- columnChildren);
- _addLabel(metadata[media.metadataLabelArtist] ?? _leafAssetToPlay.artist,
- Colors.grey[600], 15.0, columnChildren);
- _addLabel(metadata[media.metadataLabelAlbum] ?? _leafAssetToPlay.album,
- Colors.grey[800], 15.0, columnChildren);
- }
-
- _addProblem(columnChildren);
-
- return Material(
- color: Colors.black,
- child: Stack(
- children: <Widget>[
- Positioned(
- left: 0.0,
- right: 0.0,
- top: 0.0,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.stretch,
- children: columnChildren,
- ),
- ),
- Positioned(
- right: 0.0,
- top: 0.0,
- child: Offstage(
- offstage: !_controller.shouldShowControlOverlay,
- child: PhysicalModel(
- elevation: 2.0,
- color: Colors.transparent,
- borderRadius: BorderRadius.circular(60.0),
- child: IconButton(
- icon: Icon(
- _assets.length == 1 ? Icons.close : Icons.arrow_back),
- iconSize: 60.0,
- onPressed: () {
- if (_assets.length == 1) {
- io.exit(0);
- return;
- }
-
- _controller.pause();
- Navigator.of(context).pop();
- },
- color: Colors.white,
- ),
- ),
- ),
- ),
- ],
- ),
- );
- }
-}
-
-/// Screen for asset selection
-class _ChooserScreen extends StatefulWidget {
- const _ChooserScreen({Key key}) : super(key: key);
-
- @override
- _ChooserScreenState createState() => _ChooserScreenState();
-}
-
-class _ChooserScreenState extends State<_ChooserScreen> {
- Widget _buildChooseButton(Asset asset) {
- IconData iconData;
-
- switch (asset.type) {
- case AssetType.movie:
- iconData = Icons.movie;
- break;
- case AssetType.song:
- iconData = Icons.music_note;
- break;
- case AssetType.playlist:
- iconData = Icons.playlist_play;
- break;
- }
-
- return RaisedButton(
- onPressed: () {
- _play(asset);
- Navigator.of(context).pushNamed('/play');
- },
- color: Colors.black,
- child: Row(
- children: <Widget>[
- Icon(
- iconData,
- size: 60.0,
- color: Colors.grey[200],
- ),
- Column(
- mainAxisAlignment: MainAxisAlignment.center,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: <Widget>[
- Text(
- asset.title ?? '(no title)',
- style: TextStyle(color: Colors.grey[200], fontSize: 18.0),
- ),
- Text(
- asset.artist ?? '',
- style: TextStyle(color: Colors.grey[600], fontSize: 13.0),
- ),
- Text(
- asset.album ?? '',
- style: TextStyle(color: Colors.grey[800], fontSize: 13.0),
- ),
- ],
- ),
- ],
- ),
- );
- }
-
- @override
- Widget build(BuildContext context) {
- return Material(
- color: Colors.black,
- child: Stack(
- children: <Widget>[
- ListView(
- itemExtent: 75.0,
- children: _assets.map(_buildChooseButton).toList(),
- ),
- Positioned(
- right: 0.0,
- top: 0.0,
- child: PhysicalModel(
- elevation: 2.0,
- color: Colors.transparent,
- child: IconButton(
- icon: Icon(Icons.close),
- iconSize: 60.0,
- onPressed: () {
- io.exit(0);
- },
- color: Colors.white,
- ),
- ),
- ),
- ],
- ),
- );
- }
-}
-
-Future<Null> main() async {
- setupLogger(name: 'mediaplayer_flutter Module');
- log.fine('Module started');
-
- // explicitly opt out of intents
- Module().registerIntentHandler(NoopIntentHandler());
-
- await _readConfig();
-
- if (_assets.isEmpty) {
- print('no assets configured');
- return;
- }
-
- if (_assets.length == 1) {
- _play(_assets[0]);
- }
-
- runApp(MaterialApp(
- title: 'Media Player',
- home: _assets.length == 1 ? const _PlaybackScreen() : _ChooserScreen(),
- routes: <String, WidgetBuilder>{
- '/play': (BuildContext context) => const _PlaybackScreen()
- },
- theme: ThemeData(primarySwatch: Colors.blue),
- debugShowCheckedModeBanner: false,
- ));
-}
diff --git a/examples/mediaplayer/mediaplayer_flutter/mediaplayer_flutter.config b/examples/mediaplayer/mediaplayer_flutter/mediaplayer_flutter.config
deleted file mode 100644
index af6643c..0000000
--- a/examples/mediaplayer/mediaplayer_flutter/mediaplayer_flutter.config
+++ /dev/null
@@ -1,6 +0,0 @@
-[
- {
- "uri": "http://ia800201.us.archive.org/12/items/BigBuckBunny_328/BigBuckBunny.ogv",
- "title": "Big Buck Bunny"
- }
-]
diff --git a/examples/mediaplayer/mediaplayer_flutter/meta/mediaplayer_flutter.cmx b/examples/mediaplayer/mediaplayer_flutter/meta/mediaplayer_flutter.cmx
deleted file mode 100644
index 82afaff..0000000
--- a/examples/mediaplayer/mediaplayer_flutter/meta/mediaplayer_flutter.cmx
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "program": {
- "data": "data/mediaplayer_flutter"
- },
- "sandbox": {
- "features": [ "isolated-persistent-storage" ],
- "services": [
- "fuchsia.fonts.Provider",
- "fuchsia.media.playback.Player",
- "fuchsia.sys.Environment",
- "fuchsia.ui.input.ImeService",
- "fuchsia.ui.policy.Presenter",
- "fuchsia.ui.scenic.Scenic"
- ]
- }
-}
-
diff --git a/examples/mediaplayer/mediaplayer_flutter/pubspec.yaml b/examples/mediaplayer/mediaplayer_flutter/pubspec.yaml
deleted file mode 100644
index 195af72..0000000
--- a/examples/mediaplayer/mediaplayer_flutter/pubspec.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2017 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Dummy for Dart analysis server.
diff --git a/public/lib/mediaplayer/OWNERS b/public/lib/mediaplayer/OWNERS
deleted file mode 100644
index dcc89ec..0000000
--- a/public/lib/mediaplayer/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-dalesat@google.com
-*
diff --git a/public/lib/mediaplayer/dart/BUILD.gn b/public/lib/mediaplayer/dart/BUILD.gn
deleted file mode 100644
index bca0837..0000000
--- a/public/lib/mediaplayer/dart/BUILD.gn
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2017 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/dart/dart_library.gni")
-
-dart_library("dart") {
- infer_package_name = true
-
- sources = [
- "audio_player_controller.dart",
- "timeline.dart",
- ]
-
- source_dir = "."
-
- deps = [
- "//sdk/fidl/fuchsia.math",
- "//sdk/fidl/fuchsia.media",
- "//sdk/fidl/fuchsia.media.audio",
- "//sdk/fidl/fuchsia.media.playback",
- "//topaz/public/dart/fidl",
- "//topaz/public/lib/settings:settings_protos",
- ]
-}
diff --git a/public/lib/mediaplayer/dart/analysis_options.yaml b/public/lib/mediaplayer/dart/analysis_options.yaml
deleted file mode 100644
index 54917c0..0000000
--- a/public/lib/mediaplayer/dart/analysis_options.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2017 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-include: ../../../analysis_options.yaml
diff --git a/public/lib/mediaplayer/dart/audio_player_controller.dart b/public/lib/mediaplayer/dart/audio_player_controller.dart
deleted file mode 100644
index 5901f0e..0000000
--- a/public/lib/mediaplayer/dart/audio_player_controller.dart
+++ /dev/null
@@ -1,354 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:io';
-
-import 'package:fidl_fuchsia_media_playback/fidl_async.dart';
-import 'package:fidl_fuchsia_math/fidl_async.dart' as geom;
-import 'package:fuchsia_services/services.dart';
-import 'package:lib.mediaplayer.dart/timeline.dart' as tl;
-import 'package:zircon/zircon.dart';
-
-/// Type for |AudioPlayerController| update callbacks.
-typedef UpdateCallback = void Function();
-
-/// Controller for audio-only playback.
-class AudioPlayerController {
- Incoming _services;
-
- PlayerProxy _player;
-
- bool _active = false;
- bool _loading = false;
- bool _playing = false;
- bool _ended = false;
- bool _hasVideo = false;
-
- tl.TimelineFunction _timelineFunction;
- Problem _problem;
-
- Map<String, String> _metadata;
-
- bool _progressBarReady = false;
- int _progressBarMicrosecondsSinceEpoch;
- int _progressBarReferenceTime;
- int _durationNanoseconds;
- double _deferredNormalizedSeek;
-
- /// Constructs a AudioPlayerController.
- AudioPlayerController(Incoming services) {
- _services = services;
- _close(); // Initialize stuff.
- }
-
- /// Called when properties have changed.
- UpdateCallback updateCallback;
-
- /// Opens a URI for playback. Only HTTP and FILE URIs are allowed. |headers|
- /// must only be supplied for HTTP/S URIs. Supplied headers will be added to
- /// every HTTP/S request issued to the URI.
- void open(Uri uri, {HttpHeaders headers}) {
- if (uri == null) {
- throw ArgumentError.notNull('uri');
- }
- if (uri.isScheme('FILE')) {
- if (headers != null) {
- throw ArgumentError.value(
- headers, 'headers', 'Not valid for FILE URIs.');
- }
- } else if (!uri.isScheme('HTTP') && !uri.isScheme('HTTPS')) {
- throw ArgumentError.value(
- uri, 'uri', 'Only HTTP/S and FILE protocols are supported.');
- }
-
- if (_active) {
- _setSource(uri, headers);
- _ended = false;
- _hasVideo = false;
- _timelineFunction = null;
- _loading = true;
- _durationNanoseconds = 0;
- _deferredNormalizedSeek = null;
- } else {
- _active = true;
-
- _createLocalPlayer(uri, headers);
- }
-
- if (updateCallback != null) {
- scheduleMicrotask(() {
- updateCallback();
- });
- }
- }
-
- /// Closes this controller, undoing a previous |open| call. Does nothing if
- /// the controller is already closed.
- void close() {
- _close();
-
- if (updateCallback != null) {
- scheduleMicrotask(() {
- updateCallback();
- });
- }
- }
-
- /// Internal version of |close|.
- void _close() {
- _active = false;
-
- if (_player != null) {
- _player.ctrl.close();
- }
-
- _player = PlayerProxy();
-
- _playing = false;
- _ended = false;
- _loading = true;
- _hasVideo = false;
-
- _problem = null;
- _metadata = null;
-
- _progressBarReady = false;
- _durationNanoseconds = 0;
- _deferredNormalizedSeek = null;
- }
-
- /// Creates a local player.
- void _createLocalPlayer(Uri uri, HttpHeaders headers) {
- _services.connectToService(_player);
- _player.onStatusChanged.listen(_handleStatusChanged);
-
- onMediaPlayerCreated(_player);
-
- _setSource(uri, headers);
- }
-
- // Sets the source uri on the media player.
- void _setSource(Uri uri, HttpHeaders headers) {
- _player
- .setFileSource(Channel.fromFile(uri.toFilePath()))
- .catchError(_handleConnectionError);
- }
-
- /// Indicates whether the player open or connected (as opposed to closed).
- bool get openOrConnected => _active;
-
- /// Indicates whether the player is in the process of loading content.
- /// A transition to false signals that the content is viable and has a
- /// duration. Metadata may arrive before or after loading transitions to
- /// false.
- bool get loading => _loading;
-
- /// Indicates whether the content has a video stream.
- bool get hasVideo => _hasVideo;
-
- /// Indicates whether the player is currently playing.
- bool get playing => _playing;
-
- /// Indicates whether the player is at end-of-stream.
- bool get ended => _ended;
-
- /// Gets the current problem, if there is one. If this value is non-null,
- /// some issue is preventing playback, and this value describes what that
- /// issue is.
- Problem get problem => _problem;
-
- /// Gets the current content metadata, if any.
- Map<String, String> get metadata => _metadata;
-
- /// Gets the duration of the content.
- Duration get duration => Duration(microseconds: _durationNanoseconds ~/ 1000);
-
- /// Gets current playback progress.
- Duration get progress {
- if (!_progressBarReady) {
- return Duration.zero;
- }
-
- return Duration(
- microseconds:
- _progressNanoseconds.clamp(0, _durationNanoseconds) ~/ 1000);
- }
-
- /// Gets current playback progress normalized to the range 0.0 to 1.0.
- double get normalizedProgress {
- int durationInMicroseconds = duration.inMicroseconds;
-
- if (durationInMicroseconds == 0) {
- return 0.0;
- }
-
- return progress.inMicroseconds / durationInMicroseconds;
- }
-
- /// Gets current playback progress in nanoseconds.
- int get _progressNanoseconds {
- // Estimate FrameInfo::presentationTime.
- if (_timelineFunction == null) {
- return 0;
- }
-
- int microseconds = (DateTime.now()).microsecondsSinceEpoch -
- _progressBarMicrosecondsSinceEpoch;
- int referenceNanoseconds = microseconds * 1000 + _progressBarReferenceTime;
- return _timelineFunction(referenceNanoseconds);
- }
-
- /// Starts or resumes playback.
- void play() {
- if (!_active || _playing) {
- return;
- }
-
- if (_ended) {
- _player.seek(0).catchError(_handleConnectionError);
- }
-
- _player.play().catchError(_handleConnectionError);
- }
-
- /// Pauses playback.
- void pause() {
- if (!_active || !_playing) {
- return;
- }
-
- _player.pause().catchError(_handleConnectionError);
- }
-
- /// Seeks to a position expressed as a Duration.
- void seek(Duration position) {
- if (!_active) {
- return;
- }
-
- int positionNanoseconds = (position.inMicroseconds * 1000).round();
-
- _player.seek(positionNanoseconds).catchError(_handleConnectionError);
- }
-
- /// Seeks to a position expressed as a normalized value in the range 0.0 to
- /// 1.0.
- void normalizedSeek(double normalizedPosition) {
- int durationInMicroseconds = duration.inMicroseconds;
-
- if (durationInMicroseconds == 0) {
- _deferredNormalizedSeek = normalizedPosition;
- return;
- }
-
- seek(Duration(
- microseconds: (normalizedPosition * durationInMicroseconds).round()));
- }
-
- // Overridden by subclasses to get access to the local player.
- void onMediaPlayerCreated(PlayerProxy player) {}
-
- void onVideoGeometryUpdated(
- geom.Size videoSize, geom.Size pixelAspectRatio) {}
-
- // Handles a status update from the player.
- void _handleStatusChanged(PlayerStatus status) {
- if (!_active) {
- return;
- }
-
- // When the timeline function changes, its reference time is likely to
- // correspond to system time, so we take the opportunity to calibrate
- // the progress bar.
- bool prepare = false;
-
- if (status.timelineFunction != null) {
- tl.TimelineFunction oldTimelineFunction = _timelineFunction;
-
- _timelineFunction = tl.TimelineFunction.fromFidl(status.timelineFunction);
-
- prepare = oldTimelineFunction != _timelineFunction;
- }
-
- _hasVideo = status.hasVideo;
- _ended = status.endOfStream;
-
- _playing = !ended &&
- _timelineFunction != null &&
- _timelineFunction.subjectDelta != 0;
-
- _problem = status.problem;
-
- if (status.metadata != null) {
- _metadata = Map.fromIterable(status.metadata.properties,
- key: (property) => property.label,
- value: (property) => property.value);
- } else {
- _metadata = null;
- }
-
- _durationNanoseconds = status.duration;
-
- if (status.duration != 0) {
- _loading = false;
- if (_deferredNormalizedSeek != null) {
- normalizedSeek(_deferredNormalizedSeek);
- _deferredNormalizedSeek = null;
- }
- }
-
- if (_progressBarReady && _progressNanoseconds < 0) {
- // We thought the progress bar was ready, but we're getting negative
- // progress values. That means our assumption about reference time
- // correlation is probably wrong. We need to prepare the progress bar
- // again. See the comment in |_prepareProgressBar|.
- // TODO(dalesat): Remove once we're given access to presentation time.
- // https://fuchsia.atlassian.net/browse/US-130
- _progressBarReady = false;
- }
-
- if (_timelineFunction != null &&
- _timelineFunction.referenceTime != 0 &&
- (!_progressBarReady || prepare)) {
- _prepareProgressBar();
- }
-
- if (status.videoSize != null && status.pixelAspectRatio != null) {
- onVideoGeometryUpdated(status.videoSize, status.pixelAspectRatio);
- }
-
- if (updateCallback != null) {
- scheduleMicrotask(() {
- updateCallback();
- });
- }
- }
-
- /// Called when the connection to the NetMediaPlayer fails.
- void _handleConnectionError(Object _) {
- _problem = Problem(type: problemConnectionFailed);
-
- if (updateCallback != null) {
- scheduleMicrotask(() {
- updateCallback();
- });
- }
- }
-
- /// Captures information required to implement the progress bar.
- void _prepareProgressBar() {
- // Capture the correlation between the system clock and the reference time
- // from the timeline function, which we assume to be roughly 'now' in the
- // FrameInfo::presentationTime sense. This is a rough approximation and
- // could break for any number of reasons. We currently have to do this
- // because flutter doesn't provide access to FrameInfo::presentationTime.
- // TODO(dalesat): Fix once we're given access to presentation time.
- // https://fuchsia.atlassian.net/browse/US-130
- _progressBarMicrosecondsSinceEpoch =
- (DateTime.now()).microsecondsSinceEpoch;
- _progressBarReferenceTime = _timelineFunction.referenceTime;
- _progressBarReady = true;
- }
-}
diff --git a/public/lib/mediaplayer/dart/pubspec.yaml b/public/lib/mediaplayer/dart/pubspec.yaml
deleted file mode 100644
index 195af72..0000000
--- a/public/lib/mediaplayer/dart/pubspec.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2017 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Dummy for Dart analysis server.
diff --git a/public/lib/mediaplayer/dart/timeline.dart b/public/lib/mediaplayer/dart/timeline.dart
deleted file mode 100644
index 0defdac..0000000
--- a/public/lib/mediaplayer/dart/timeline.dart
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'package:fidl_fuchsia_media/fidl_async.dart' as media;
-
-/// Immutable rate of a subject timeline with respect to a reference timeline
-/// (subject / reference) expressed as the ratio of two ints.
-class TimelineRate {
- /// The change in subject time that correlates to referenceDelta.
- final int subjectDelta;
-
- /// The change in reference time that correlates to subjectDelta. May not
- /// be zero.
- final int referenceDelta;
-
- // A multiplier for float-to-TimelineRate conversions chosen because doubles
- // have a 52-bit mantissa.
- static const int _floatFactor = 1 << 52;
-
- /// Constructs a TimelineRate from a subject delta and a reference delta.
- factory TimelineRate({
- int subjectDelta = 0,
- int referenceDelta = 1,
- }) {
- assert(referenceDelta != 0);
- int gcd = subjectDelta.gcd(referenceDelta);
- return TimelineRate._(subjectDelta ~/ gcd, referenceDelta ~/ gcd);
- }
-
- /// Constructs a TimelineRate from a double.
- factory TimelineRate.fromDouble(double asDouble) {
- if (asDouble > 1.0) {
- return TimelineRate(
- subjectDelta: _floatFactor,
- referenceDelta: (_floatFactor * asDouble).toInt(),
- );
- } else {
- return TimelineRate(
- subjectDelta: _floatFactor ~/ asDouble,
- referenceDelta: _floatFactor,
- );
- }
- }
-
- /// Internal constructor.
- const TimelineRate._(this.subjectDelta, this.referenceDelta);
-
- /// A rate of 0 / 1.
- static const TimelineRate zero = TimelineRate._(0, 1);
-
- /// The number of nanoseconds in a second.
- static const TimelineRate nanosecondsPerSecond =
- TimelineRate._(1000000000, 1);
-
- /// The inverse of this rate. Asserts if this.subjectDelta is zero.
- TimelineRate get inverse => TimelineRate(
- subjectDelta: referenceDelta,
- referenceDelta: subjectDelta,
- );
-
- /// Returns the product of this TimelineRate with another TimelineRate.
- TimelineRate product(TimelineRate other) => TimelineRate(
- subjectDelta: subjectDelta * other.subjectDelta,
- referenceDelta: referenceDelta * other.referenceDelta,
- );
-
- /// Returns the product of this TimelineRate with an int as an int.
- int operator *(int value) => (value * subjectDelta) ~/ referenceDelta;
-
- @override
- int get hashCode => subjectDelta.hashCode ^ referenceDelta.hashCode;
-
- @override
- bool operator ==(Object other) =>
- other is TimelineRate &&
- subjectDelta == other.subjectDelta &&
- referenceDelta == other.referenceDelta;
-
- @override
- String toString() => '$subjectDelta/$referenceDelta';
-}
-
-/// Immutable linear function that produces a subject time from a reference
-/// time.
-class TimelineFunction {
- /// The subject time that corresponds to referenceTime.
- final int subjectTime;
-
- /// The reference time that corresponds to subjectTime.
- final int referenceTime;
-
- /// The slope of the function (subject / reference).
- final TimelineRate rate;
-
- /// Constructs a TimelineFunction from a pair of correlated values and a
- /// TimelineRate.
- const TimelineFunction({
- this.subjectTime = 0,
- this.referenceTime = 0,
- this.rate = TimelineRate.zero,
- });
-
- /// Constructs a TimelineFunction from a FIDL TimelineFunction struct.
- TimelineFunction.fromFidl(media.TimelineFunction timelineFunction)
- : subjectTime = timelineFunction.subjectTime,
- referenceTime = timelineFunction.referenceTime,
- rate = TimelineRate(
- subjectDelta: timelineFunction.subjectDelta,
- referenceDelta: timelineFunction.referenceDelta,
- );
-
- /// The change in subject time that correlates to referenceDelta.
- int get subjectDelta => rate.subjectDelta;
-
- /// The change in reference time that correlates to subjectDelta. Never zero.
- int get referenceDelta => rate.referenceDelta;
-
- /// Applies the function to an int.
- int call(int referenceInput) => apply(referenceInput);
-
- /// Applies the function to an int.
- int apply(int referenceInput) =>
- rate * (referenceInput - referenceTime) + subjectTime;
-
- /// Applies the inverse of the function to an int. Asserts if subjectDelta is
- /// zero.
- int applyInverse(int subjectInput) {
- assert(rate.subjectDelta != 0);
- return rate.inverse * (subjectInput - subjectTime) + referenceTime;
- }
-
- /// Gets the inverse of this function. sserts if subjectDelta is zero.
- TimelineFunction get inverse {
- assert(rate.subjectDelta != 0);
- return TimelineFunction(
- subjectTime: referenceTime,
- referenceTime: subjectTime,
- rate: rate.inverse,
- );
- }
-
- /// Composes this TimelineFunction with another TimelineFunction.
- TimelineFunction operator *(TimelineFunction other) => TimelineFunction(
- subjectTime: apply(other.subjectTime),
- referenceTime: other.referenceTime,
- rate: rate.product(other.rate),
- );
-
- @override
- int get hashCode =>
- subjectTime.hashCode ^ referenceTime.hashCode ^ rate.hashCode;
-
- @override
- bool operator ==(Object other) =>
- other is TimelineFunction &&
- subjectTime == other.subjectTime &&
- referenceTime == other.referenceTime &&
- rate == other.rate;
-
- @override
- String toString() => '$subjectTime:$referenceTime@$rate';
-}
diff --git a/public/lib/mediaplayer/flutter/BUILD.gn b/public/lib/mediaplayer/flutter/BUILD.gn
deleted file mode 100644
index 5135bd8..0000000
--- a/public/lib/mediaplayer/flutter/BUILD.gn
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 2017 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/dart/dart_library.gni")
-
-dart_library("flutter") {
- infer_package_name = true
-
- source_dir = "."
-
- # Unclear non-standard directory structure
- sources_required = false
-
- sources = [
- "media_player.dart",
- "media_player_controller.dart",
- "progress_notifier.dart",
- ]
-
- deps = [
- "//sdk/fidl/fuchsia.media",
- "//third_party/dart-pkg/git/flutter/packages/flutter",
- "//topaz/public/dart/fuchsia_scenic",
- "//topaz/public/dart/fuchsia_scenic_flutter",
- "//topaz/public/lib/mediaplayer/dart",
- ]
-}
diff --git a/public/lib/mediaplayer/flutter/README.md b/public/lib/mediaplayer/flutter/README.md
deleted file mode 100644
index 6ec449f..0000000
--- a/public/lib/mediaplayer/flutter/README.md
+++ /dev/null
@@ -1,42 +0,0 @@
-# Flutter Library for Media
-
-This directory contains dart code to help play media in a Flutter app. The
-adjacent `lib\dart` directory contains more dart code that has no Flutter
-dependency. This directory depends on `lib\dart`.
-
-## MediaPlayerController
-
-`MediaPlayerController` is a class that manages FIDL media players. This class
-is distinct from the widget, because it typically needs to outlive the widget
-state.
-
-A controller instance controls a single media player, either on the local device
-or on a remote device. It will create a local player, but it doesn't have any
-way to create a remote player. A remote player must be started somehow, then
-a `MediaPlayerController` will connect to it via the `connectToRemote` method.
-To create a local player, call the `open` method.
-
-Once a local or remote player is open, it can be controlled using various
-methods. It also exposes properties that let the application know what's going
-on. The controller implements `Listenable`, so applications can know when
-its properties have changed.
-
-## MediaPlayer (the widget)
-
-`MediaPlayer` is a stateful widget that shows video and provides some UI such
-as play/pause buttons and a touchable progress bar. It can also be used for
-audio-only content, in which case only the UI is shown. Its constructor accepts
-a `MediaPlayerController`.
-
-The layout logic of a `MediaPlayer` attempts to preserve proper video aspect
-ratio if possible. If both dimensions are constrained, the video will be
-stretched accordingly. Otherwise, the widget will be as large as it can be
-while meeting its imposed constraints and maintaining correct aspect ratio.
-
-## ProgressNotifier
-
-`ProgressNotifier` is a `ChangeNotifier` for animating widgets that reflect
-player progress. This class can be used with `AnimatedBuilder` to create widgets
-that animate based on the progress of an `AudioPlayerController` or
-`MediaPlayerController`. Use `ProgressNotifier` to animate a progress bar or
-other progress indication with a minimum of redrawing.
diff --git a/public/lib/mediaplayer/flutter/analysis_options.yaml b/public/lib/mediaplayer/flutter/analysis_options.yaml
deleted file mode 100644
index 54917c0..0000000
--- a/public/lib/mediaplayer/flutter/analysis_options.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2017 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-include: ../../../analysis_options.yaml
diff --git a/public/lib/mediaplayer/flutter/media_player.dart b/public/lib/mediaplayer/flutter/media_player.dart
deleted file mode 100644
index 2f713ae..0000000
--- a/public/lib/mediaplayer/flutter/media_player.dart
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'package:fuchsia_scenic_flutter/child_view.dart' show ChildView;
-import 'package:lib.mediaplayer.flutter/media_player_controller.dart';
-import 'package:lib.mediaplayer.flutter/progress_notifier.dart';
-
-import 'package:flutter/material.dart';
-import 'package:flutter/widgets.dart';
-
-/// Widget that plays media given a URL (including file: URLs).
-class MediaPlayer extends StatefulWidget {
- /// The controller exposed by this widget.
- final MediaPlayerController controller;
-
- /// Constructs a [MediaPlayer] from an existing controller.
- const MediaPlayer(this.controller, {Key key}) : super(key: key);
-
- @override
- _MediaPlayerState createState() => _MediaPlayerState();
-}
-
-/// The state of a MediaPlayer widget.
-class _MediaPlayerState extends State<MediaPlayer> {
- ProgressNotifier _secondsNotifier;
- ProgressNotifier _sliderNotifier;
-
- @override
- void initState() {
- assert(widget.controller != null);
- _hookController(widget.controller);
- super.initState();
- }
-
- @override
- void dispose() {
- _unhookController(widget.controller);
- super.dispose();
- }
-
- @override
- void didUpdateWidget(MediaPlayer oldWidget) {
- super.didUpdateWidget(oldWidget);
- if (oldWidget.controller != widget.controller) {
- _unhookController(oldWidget.controller);
- _hookController(widget.controller);
- }
- }
-
- /// Adds notification hooks to |controller|.
- void _hookController(MediaPlayerController controller) {
- controller.addListener(_handleControllerChanged);
- _secondsNotifier = ProgressNotifier(controller);
- _sliderNotifier = ProgressNotifier(controller);
- }
-
- /// Removes notification hooks from |controller|.
- void _unhookController(MediaPlayerController controller) {
- controller.removeListener(_handleControllerChanged);
- _secondsNotifier?.dispose();
- _secondsNotifier = null;
- _sliderNotifier?.dispose();
- _sliderNotifier = null;
- }
-
- /// Handles change notifications from the controller.
- void _handleControllerChanged() {
- setState(() {});
- }
-
- /// Converts a duration to a string indicating seconds, such as '1:15:00' or
- /// '2:40'
- static String _durationToString(Duration duration) {
- int seconds = duration.inSeconds;
- int minutes = seconds ~/ 60;
- seconds %= 60;
- int hours = minutes ~/ 60;
- minutes %= 60;
-
- String hoursString = hours == 0 ? '' : '$hours:';
- String minutesString =
- (hours == 0 || minutes > 9) ? '$minutes:' : '0$minutes:';
- String secondsString = seconds > 9 ? '$seconds' : '0$seconds';
-
- return '$hoursString$minutesString$secondsString';
- }
-
- /// Gets the desired size of this widget.
- Size get _layoutSize {
- Size size = widget.controller.videoPhysicalSize;
-
- if (size.width == 0) {
- size = Size(320.0, 45.0);
- } else {
- size = size / MediaQuery.of(context).devicePixelRatio;
- }
-
- return size;
- }
-
- /// Builds an overlay widget that contains playback controls.
- Widget _buildControlOverlay() {
- assert(debugCheckHasMaterial(context));
-
- return Stack(
- children: <Widget>[
- Center(
- child: PhysicalModel(
- elevation: 2.0,
- color: Colors.transparent,
- borderRadius: BorderRadius.circular(60.0),
- child: IconButton(
- icon: widget.controller.problem != null
- ? const Icon(Icons.error_outline)
- : widget.controller.loading
- ? const Icon(Icons.hourglass_empty)
- : widget.controller.playing
- ? const Icon(Icons.pause)
- : Icon(Icons.play_arrow),
- iconSize: 60.0,
- onPressed: () {
- if (widget.controller.playing) {
- widget.controller.pause();
- } else {
- widget.controller.play();
- }
- },
- color: Colors.white,
- ),
- ),
- ),
- Positioned(
- left: 2.0,
- bottom: 8.0,
- child: PhysicalModel(
- elevation: 2.0,
- color: Colors.transparent,
- borderRadius: BorderRadius.circular(10.0),
- child: AnimatedBuilder(
- animation:
- _secondsNotifier.withResolution(const Duration(seconds: 1)),
- builder: (BuildContext context, Widget child) => Container(
- width: 65.0,
- child: Text(
- _durationToString(widget.controller.progress),
- style: TextStyle(color: Colors.white),
- textAlign: TextAlign.center,
- ),
- ),
- ),
- ),
- ),
- Positioned(
- left: 48.0,
- right: 48.0,
- bottom: 0.0,
- child: PhysicalModel(
- elevation: 3.0,
- color: Colors.transparent,
- child: LayoutBuilder(
- builder: (BuildContext context, BoxConstraints constraints) =>
- AnimatedBuilder(
- animation: _sliderNotifier.withExcursion(
- constraints.maxWidth, context),
- builder: (BuildContext context, Widget child) => Slider(
- min: 0.0,
- max: 1.0,
- activeColor: Colors.red[900],
- value: widget.controller.normalizedProgress,
- onChanged: (double value) =>
- widget.controller.normalizedSeek(value)),
- ),
- ),
- ),
- ),
- Positioned(
- right: 2.0,
- bottom: 8.0,
- child: PhysicalModel(
- elevation: 2.0,
- color: Colors.transparent,
- borderRadius: BorderRadius.circular(10.0),
- child: Container(
- width: 65.0,
- child: Text(
- _durationToString(widget.controller.duration),
- style: TextStyle(color: Colors.white),
- textAlign: TextAlign.center,
- ),
- ),
- ),
- ),
- ],
- );
- }
-
- @override
- Widget build(BuildContext context) {
- return AspectRatio(
- aspectRatio: _layoutSize.width / _layoutSize.height,
- child: Stack(
- children: <Widget>[
- GestureDetector(
- onTap: widget.controller.brieflyShowControlOverlay,
- child: ChildView(
- connection: widget.controller.videoViewConnection),
- ),
- Offstage(
- offstage: !widget.controller.shouldShowControlOverlay,
- child: _buildControlOverlay(),
- ),
- ],
- ),
- );
- }
-}
diff --git a/public/lib/mediaplayer/flutter/media_player_controller.dart b/public/lib/mediaplayer/flutter/media_player_controller.dart
deleted file mode 100644
index 62e5c72..0000000
--- a/public/lib/mediaplayer/flutter/media_player_controller.dart
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:io';
-
-import 'package:fidl_fuchsia_math/fidl_async.dart' as geom;
-import 'package:fidl_fuchsia_media_playback/fidl_async.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/widgets.dart';
-import 'package:fuchsia_services/services.dart';
-import 'package:fuchsia_scenic/views.dart';
-import 'package:fuchsia_scenic_flutter/child_view_connection.dart';
-import 'package:lib.mediaplayer.dart/audio_player_controller.dart';
-
-/// Controller for MediaPlayer widgets.
-class MediaPlayerController extends AudioPlayerController
- implements Listenable {
- final List<VoidCallback> _listeners = <VoidCallback>[];
-
- Timer _hideTimer;
-
- ChildViewConnection _videoViewConnection;
-
- Size _videoSize = Size.zero;
-
- bool _disposed = false;
- bool _wasActive;
-
- /// Constructs a MediaPlayerController.
- MediaPlayerController(Incoming services) : super(services) {
- updateCallback = _notifyListeners;
- _close(); // Initialize stuff.
- }
-
- @override
- void open(Uri uri, {HttpHeaders headers}) {
- _wasActive = openOrConnected;
- super.open(uri, headers: headers);
- scheduleMicrotask(_notifyListeners);
- }
-
- @override
- void onMediaPlayerCreated(PlayerProxy player) {
- if (!_wasActive) {
- final ViewTokenPair viewTokens = ViewTokenPair();
-
- player.createView(viewTokens.viewToken);
- _videoViewConnection = ChildViewConnection(viewTokens.viewHolderToken);
- }
- }
-
- @override
- void close() {
- _close();
- super.close();
- scheduleMicrotask(_notifyListeners);
- }
-
- void _close() {
- _videoViewConnection = null;
- }
-
- @override
- void addListener(VoidCallback listener) {
- if (_disposed) {
- throw StateError('Object disposed');
- }
-
- _listeners.add(listener);
- }
-
- @override
- void removeListener(VoidCallback listener) {
- if (_disposed) {
- throw StateError('Object disposed');
- }
-
- _listeners.remove(listener);
- }
-
- void _notifyListeners() {
- for (VoidCallback listener in _listeners) {
- listener();
- }
- }
-
- /// Discards any resources used by the object. After this is called, the
- /// object is not in a usable state and should be discarded (calls to
- /// addListener and removeListener will throw after the object is disposed).
- @mustCallSuper
- void dispose() {
- _disposed = true;
- close();
- _hideTimer?.cancel();
- _listeners.clear();
- }
-
- /// Determines whether the control overlay should be shown.
- bool get shouldShowControlOverlay {
- return !hasVideo || !playing || _hideTimer != null;
- }
-
- /// Shows the control overlay for [overlayAutoHideDuration].
- void brieflyShowControlOverlay() {
- bool prevShouldShowControlOverlay = shouldShowControlOverlay;
-
- _hideTimer?.cancel();
-
- _hideTimer = Timer(overlayAutoHideDuration, () {
- _hideTimer = null;
- if (!shouldShowControlOverlay) {
- _notifyListeners();
- }
- });
-
- if (prevShouldShowControlOverlay != shouldShowControlOverlay) {
- _notifyListeners();
- }
- }
-
- /// The duration to show the control overlay when [brieflyShowControlOverlay]
- /// is called. The default is 3 seconds.
- Duration overlayAutoHideDuration = Duration(seconds: 3);
-
- /// Gets the physical size of the video.
- Size get videoPhysicalSize => hasVideo ? _videoSize : Size.zero;
-
- /// Gets the video view connection.
- ChildViewConnection get videoViewConnection => _videoViewConnection;
-
- @override
- void onVideoGeometryUpdated(geom.Size videoSize, geom.Size pixelAspectRatio) {
- if (!openOrConnected) {
- return;
- }
-
- double ratio =
- pixelAspectRatio.width.toDouble() / pixelAspectRatio.height.toDouble();
-
- _videoSize =
- Size(videoSize.width.toDouble() * ratio, videoSize.height.toDouble());
-
- scheduleMicrotask(_notifyListeners);
- }
-}
diff --git a/public/lib/mediaplayer/flutter/media_progress.dart b/public/lib/mediaplayer/flutter/media_progress.dart
deleted file mode 100644
index b7cc9e1..0000000
--- a/public/lib/mediaplayer/flutter/media_progress.dart
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2018 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'package:lib.widgets/model.dart';
-
-/// Tracks progress of Media playback
-class MediaProgress extends Model {
- /// Constructor
- MediaProgress(this._durationMsec, this._normalizedProgress);
-
- /// Progress through media in the range [0..1]
- double _normalizedProgress;
-
- /// Full length of the media
- int _durationMsec;
-
- /// Progress through media as an absolute Duration.
- Duration get position => Duration(milliseconds: positionMsec);
-
- /// Progress through media as absolute milliseconds.
- int get positionMsec => (_durationMsec * _normalizedProgress).floor();
-
- /// Progress of media playback normalized in the range [0.0 .. 1.0];
- double get normalizedProgress => _normalizedProgress;
-
- /// Duration fo the vide in milliseconds
- int get durationMsec => _durationMsec;
-
- /// Update the duration of the media.
- set durationMsec(int durationMsec) {
- _durationMsec = durationMsec;
- notifyListeners();
- }
-
- /// Update the normalized progress of the media. This should be called
- /// with the value from the media player and is clamped to the range
- /// [0.0 .. 1.0].
- set normalizedProgress(double normalizedProgress) {
- _normalizedProgress = normalizedProgress;
- notifyListeners();
- }
-}
diff --git a/public/lib/mediaplayer/flutter/progress_notifier.dart b/public/lib/mediaplayer/flutter/progress_notifier.dart
deleted file mode 100644
index 5aa85c1..0000000
--- a/public/lib/mediaplayer/flutter/progress_notifier.dart
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:lib.mediaplayer.dart/audio_player_controller.dart';
-
-import 'package:flutter/foundation.dart';
-import 'package:flutter/widgets.dart';
-
-/// Notifier for animating widgets that reflect player progress. This class
-/// can be used with |AnimatedBuilder| to create widgets that animate based on
-/// the progress of an |AudioPlayerController| or |MediaPlayerController|.
-/// Builders should call either |withResolution| or |withExcursion|, typically
-/// when setting |AnimatedBuilder.animation|. Builders that call those methods
-/// should run when the controller updates. This is because |ProgressNotifier|
-/// doesn't allow for transitions such as play/pause or seeking. It needs the
-/// one of the 'with' methods to be called when those transitions occur.
-class ProgressNotifier extends ChangeNotifier {
- AudioPlayerController _controller;
- Duration _resolution;
- Timer _timer;
- bool _disposed = false;
-
- /// Constructs a |ProgressNotifier|.
- ProgressNotifier(this._controller) : assert(_controller != null);
-
- @override
- void dispose() {
- _disposed = true;
- _controller = null;
- _timer?.cancel();
- _timer = null;
- super.dispose();
- }
-
- /// Registers a one-time progress callback with the controller.
- void _register() {
- if (!_controller.playing) {
- _timer = null;
- return;
- }
-
- // TODO(dalesat): Take the rate into account once we support that.
-
- int resolutionMicroseconds = _resolution.inMicroseconds;
- int delayMicroseconds = resolutionMicroseconds -
- (_controller.progress.inMicroseconds % resolutionMicroseconds);
-
- _timer = Timer(Duration(microseconds: delayMicroseconds), () {
- _timer = null;
-
- if (_disposed || !_controller.playing) {
- return;
- }
-
- notifyListeners();
- _register();
- });
- }
-
- /// Sets the resolution and returns this |ProgressNotifier|. This method
- /// should be called in a builder that runs when the controller notifies of
- /// a state change.
- // ignore: avoid_returning_this
- ProgressNotifier withResolution(Duration resolution) {
- if (_disposed) {
- return this;
- }
-
- if (_timer == null || _resolution != resolution) {
- _resolution = resolution;
- _timer?.cancel();
- _register();
- }
-
- return this;
- }
-
- /// Sets the excursion and returns this |ProgressNotifier|. This method
- /// should be called in a builder that runs when the controller notifies of
- /// a state change. This method is useful for sliders where |excursion| is
- /// the distance the slider moves. Use |LayoutBuilder| to get the width of
- /// the slider.
- ProgressNotifier withExcursion(double excursion, BuildContext context) {
- double effectiveExcursion =
- excursion * MediaQuery.of(context).devicePixelRatio;
- return withResolution(Duration(
- microseconds:
- (_controller.duration.inMicroseconds / effectiveExcursion).ceil()));
- }
-}
diff --git a/public/lib/mediaplayer/flutter/pubspec.yaml b/public/lib/mediaplayer/flutter/pubspec.yaml
deleted file mode 100644
index 195af72..0000000
--- a/public/lib/mediaplayer/flutter/pubspec.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2017 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Dummy for Dart analysis server.