Skip to content

Commit

Permalink
Feature/memory player (jhomlala#134)
Browse files Browse the repository at this point in the history
* Memory player implementation

* Added factories for DataSource

* Refactored data sources

* Fixed placeholder showing after full screen when using showPlaceholderUntilPlay

* Added setControlsVisibility to BetterPlayerController

* Removed showControlsOnInitialize from BetterPlayerConfiguration

* Fixed cupertino controls issue with hasError

* Dartfmt
  • Loading branch information
jhomlala authored Nov 15, 2020
1 parent beb875a commit 943798b
Show file tree
Hide file tree
Showing 16 changed files with 428 additions and 30 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## 0.0.34
* Added memory data source
* Added factories: network, file, memory for BetterPlayerDataSource
* Fixed missing useHlsTracks implementation
* Fixed placeholder showing after full screen when using showPlaceholderUntilPlay
* Added setControlsVisibility to BetterPlayerController
* [BREAKING_CHANGE] Removed showControlsOnInitialize from BetterPlayerConfiguration. Use BetterPlayerControlsConfiguration to set showControlsOnInitialize parameter.
* Fixed cupertino controls issue with hasError

## 0.0.33
* Fixed BetterPlayerEvent visibility
* Fixed lazy initialization, when first data source is passed after player finishes first render
Expand Down
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ This plugin is based on [Chewie](https://github.com/brianegan/chewie). Chewie is

```yaml
dependencies:
better_player: ^0.0.33
better_player: ^0.0.34
```
2. Install it
Expand Down Expand Up @@ -515,7 +515,10 @@ Possible configuration options:
```

### BetterPlayerDataSource
Define source for one video in your app.
Define source for one video in your app. There are 3 types of data sources:
* Network - data source which uses url to play video from external resources
* File - data source which uses url to play video from internal resources
* Memory - data source which uses list of bytes to play video from memory
```dart
var dataSource = BetterPlayerDataSource(
BetterPlayerDataSourceType.NETWORK,
Expand All @@ -528,6 +531,10 @@ Define source for one video in your app.
);
```

You can use type specific factories to build your data source.
Use BetterPlayerDataSource.network to build network data source, BetterPlayerDataSource.file to build file data source and BetterPlayerDataSource.memory
to build memory data source.

Possible configuration options:
```
///Type of source of video
Expand Down
72 changes: 72 additions & 0 deletions example/lib/pages/controller_controls_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import 'package:better_player/better_player.dart';
import 'package:better_player_example/constants.dart';
import 'package:flutter/material.dart';

class ControllerControlsPage extends StatefulWidget {
@override
_ControllerControlsPageState createState() => _ControllerControlsPageState();
}

class _ControllerControlsPageState extends State<ControllerControlsPage> {
BetterPlayerController _betterPlayerController;

@override
void initState() {
BetterPlayerConfiguration betterPlayerConfiguration =
BetterPlayerConfiguration(
aspectRatio: 16 / 9,
fit: BoxFit.contain,
);
BetterPlayerDataSource dataSource = BetterPlayerDataSource(
BetterPlayerDataSourceType.NETWORK, Constants.elephantDreamVideoUrl);
_betterPlayerController = BetterPlayerController(betterPlayerConfiguration);
_betterPlayerController.setupDataSource(dataSource);
super.initState();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Controller controls page"),
),
body: Column(
children: [
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(
"Control player with BetterPlayerController",
style: TextStyle(fontSize: 16),
),
),
AspectRatio(
aspectRatio: 16 / 9,
child: BetterPlayer(controller: _betterPlayerController),
),
Wrap(
children: [
FlatButton(
child: Text("Play"), onPressed: _betterPlayerController.play),
FlatButton(
child: Text("Pause"),
onPressed: _betterPlayerController.pause),
FlatButton(
child: Text("Hide controls"),
onPressed: () {
_betterPlayerController.setControlsVisibility(false);
},
),
FlatButton(
child: Text("Show controls"),
onPressed: () {
_betterPlayerController.setControlsVisibility(true);
},
),
],
)
],
),
);
}
}
62 changes: 62 additions & 0 deletions example/lib/pages/memory_player_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import 'dart:io';

import 'package:better_player/better_player.dart';
import 'package:better_player_example/constants.dart';
import 'package:better_player_example/utils.dart';
import 'package:flutter/material.dart';

class MemoryPlayerPage extends StatefulWidget {
@override
_MemoryPlayerPageState createState() => _MemoryPlayerPageState();
}

class _MemoryPlayerPageState extends State<MemoryPlayerPage> {
BetterPlayerController _betterPlayerController;

@override
void initState() {
BetterPlayerConfiguration betterPlayerConfiguration =
BetterPlayerConfiguration(
aspectRatio: 16 / 9,
fit: BoxFit.contain,
);

_betterPlayerController = BetterPlayerController(betterPlayerConfiguration);
_setupDataSource();
super.initState();
}

void _setupDataSource() async {
var filePath = await Utils.getFileUrl(Constants.fileTestVideoUrl);
File file = File(filePath);

List<int> bytes = file.readAsBytesSync().buffer.asUint8List();
BetterPlayerDataSource dataSource = BetterPlayerDataSource.memory(bytes);
_betterPlayerController.setupDataSource(dataSource);
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Memory player"),
),
body: Column(
children: [
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(
"Memory player with plays video from bytes.",
style: TextStyle(fontSize: 16),
),
),
AspectRatio(
aspectRatio: 16 / 9,
child: BetterPlayer(controller: _betterPlayerController),
),
],
),
);
}
}
8 changes: 8 additions & 0 deletions example/lib/pages/welcome_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import 'dart:io';

import 'package:better_player_example/pages/basic_player_page.dart';
import 'package:better_player_example/pages/cache_page.dart';
import 'package:better_player_example/pages/controller_controls_page.dart';
import 'package:better_player_example/pages/controls_configuration_page.dart';
import 'package:better_player_example/pages/event_listener_page.dart';
import 'package:better_player_example/pages/hls_subtitles_page.dart';
import 'package:better_player_example/pages/hls_tracks_page.dart';
import 'package:better_player_example/pages/memory_player_page.dart';
import 'package:better_player_example/pages/normal_player_page.dart';
import 'package:better_player_example/pages/playlist_page.dart';
import 'package:better_player_example/pages/resolutions_page.dart';
Expand Down Expand Up @@ -95,6 +97,12 @@ class _WelcomePageState extends State<WelcomePage> {
_buildExampleElementWidget("Rotation and fit", () {
_navigateToPage(RotationAndFitPage());
}),
_buildExampleElementWidget("Memory player", () {
_navigateToPage(MemoryPlayerPage());
}),
_buildExampleElementWidget("Controller controls page", () {
_navigateToPage(ControllerControlsPage());
}),
];
}

Expand Down
6 changes: 0 additions & 6 deletions lib/src/configuration/better_player_configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ class BetterPlayerConfiguration {
/// Whether or not the video should loop
final bool looping;

/// Weather or not to show the controls when initializing the widget.
final bool showControlsOnInitialize;

/// When the video playback runs into an error, you can build a custom
/// error message.
final Widget Function(BuildContext context, String errorMessage) errorBuilder;
Expand Down Expand Up @@ -94,7 +91,6 @@ class BetterPlayerConfiguration {
this.placeholder,
this.showPlaceholderUntilPlay = false,
this.overlay,
this.showControlsOnInitialize = true,
this.errorBuilder,
this.allowedScreenSleep = true,
this.fullScreenAspectRatio,
Expand Down Expand Up @@ -151,8 +147,6 @@ class BetterPlayerConfiguration {
fullScreenByDefault: fullScreenByDefault ?? this.fullScreenByDefault,
placeholder: placeholder ?? this.placeholder,
overlay: overlay ?? this.overlay,
showControlsOnInitialize:
showControlsOnInitialize ?? this.showControlsOnInitialize,
errorBuilder: errorBuilder ?? this.errorBuilder,
allowedScreenSleep: allowedScreenSleep ?? this.allowedScreenSleep,
deviceOrientationsOnFullScreen:
Expand Down
78 changes: 77 additions & 1 deletion lib/src/configuration/better_player_data_source.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,13 @@ class BetterPlayerDataSource {
///Optional cache configuration, used only for network data sources
final BetterPlayerCacheConfiguration cacheConfiguration;

///List of bytes, used only in memory player
final List<int> bytes;

BetterPlayerDataSource(
this.type,
this.url, {
this.bytes,
this.subtitles,
this.liveStream = false,
this.headers,
Expand All @@ -49,11 +53,82 @@ class BetterPlayerDataSource {
this.hlsTrackNames,
this.resolutions,
this.cacheConfiguration,
});
}) : assert(
((type == BetterPlayerDataSourceType.NETWORK ||
type == BetterPlayerDataSourceType.FILE) &&
url != null) ||
(type == BetterPlayerDataSourceType.MEMORY &&
bytes?.isNotEmpty == true),
"Url can't be null in network or file data source | bytes can't be null when using memory data source");

///Factory method to build network data source which uses url as data source
///Bytes parameter is not used in this data source.
factory BetterPlayerDataSource.network(
String url, {
List<BetterPlayerSubtitlesSource> subtitles,
bool liveStream,
Map<String, String> headers,
bool useHlsSubtitles,
bool useHlsTracks,
Map<String, String> qualities,
BetterPlayerCacheConfiguration cacheConfiguration,
}) {
return BetterPlayerDataSource(
BetterPlayerDataSourceType.NETWORK,
url,
subtitles: subtitles,
liveStream: liveStream,
headers: headers,
useHlsSubtitles: useHlsSubtitles,
useHlsTracks: useHlsTracks,
resolutions: qualities,
cacheConfiguration: cacheConfiguration,
);
}

///Factory method to build file data source which uses url as data source.
///Bytes parameter is not used in this data source.
factory BetterPlayerDataSource.file(
String url, {
List<BetterPlayerSubtitlesSource> subtitles,
bool useHlsSubtitles,
bool useHlsTracks,
Map<String, String> qualities,
BetterPlayerCacheConfiguration cacheConfiguration,
}) {
return BetterPlayerDataSource(
BetterPlayerDataSourceType.NETWORK,
url,
subtitles: subtitles,
useHlsSubtitles: useHlsSubtitles,
useHlsTracks: useHlsTracks,
resolutions: qualities,
);
}

///Factory method to build network data source which uses bytes as data source.
///Url parameter is not used in this data source.
factory BetterPlayerDataSource.memory(List<int> bytes,
{List<BetterPlayerSubtitlesSource> subtitles,
bool useHlsSubtitles,
bool useHlsTracks,
Map<String, String> qualities,
BetterPlayerCacheConfiguration cacheConfiguration}) {
return BetterPlayerDataSource(
BetterPlayerDataSourceType.MEMORY,
"",
bytes: bytes,
subtitles: subtitles,
useHlsSubtitles: useHlsSubtitles,
useHlsTracks: useHlsTracks,
resolutions: qualities,
);
}

BetterPlayerDataSource copyWith({
BetterPlayerDataSourceType type,
String url,
List<int> bytes,
List<BetterPlayerSubtitlesSource> subtitles,
bool liveStream,
Map<String, String> headers,
Expand All @@ -65,6 +140,7 @@ class BetterPlayerDataSource {
return BetterPlayerDataSource(
type ?? this.type,
url ?? this.url,
bytes: bytes ?? this.bytes,
subtitles: subtitles ?? this.subtitles,
liveStream: liveStream ?? this.liveStream,
headers: headers ?? this.headers,
Expand Down
2 changes: 1 addition & 1 deletion lib/src/configuration/better_player_data_source_type.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
///Source types of video. Network type is used for videos that are hosted on
///the web service. File type is used for videos that will be read from
/// mobile device.
enum BetterPlayerDataSourceType { NETWORK, FILE }
enum BetterPlayerDataSourceType { NETWORK, FILE, MEMORY }
2 changes: 1 addition & 1 deletion lib/src/controls/better_player_controls_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ abstract class BetterPlayerControlsState<T extends StatefulWidget>
);
}

///Latest value can be null
bool isLoading(VideoPlayerValue latestValue) {
assert(latestValue != null, "Latest value can't be null");
if (latestValue != null) {
if (!latestValue.isPlaying && latestValue.duration == null) {
return true;
Expand Down
Loading

0 comments on commit 943798b

Please sign in to comment.