Skip to content
This repository has been archived by the owner on May 28, 2024. It is now read-only.

Commit

Permalink
Merge pull request #13 from lunofono/playlist
Browse files Browse the repository at this point in the history
Implement playlist playing
  • Loading branch information
llucax authored Feb 3, 2021
2 parents bf7a4ef + 9ef35e8 commit 40b4834
Show file tree
Hide file tree
Showing 42 changed files with 4,484 additions and 2,864 deletions.
4 changes: 3 additions & 1 deletion .githooks/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ fi

# Run flutter format, analyze and test
(
pre=$(git stash list | wc -l)
git stash --include-untracked --keep-index &&
trap 'r=$?; git stash pop; exit $r' EXIT
trap 'r=$?; test "$post" -gt "$pre" && git stash pop; exit $r' EXIT
post=$(git stash list | wc -l)
git status
$(git rev-parse --show-toplevel)/tool/ci || exit $?
) || exit $?
Expand Down
5 changes: 5 additions & 0 deletions .projections.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"lib/src/*.dart": { "alternate": "test/unit/{}_test.dart", "type": "source" },
"test/unit/*_test.dart": { "alternate": "lib/src/{}.dart", "type": "test" },
"*": { "make" : "tool/ci" }
}
Binary file added example/assets/heilshorn-cows2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions example/assets/heilshorn-cows2.md
80 changes: 78 additions & 2 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ class MyApp extends StatelessWidget {

final bundle = Bundle(
GridMenu(
rows: 2,
columns: 1,
rows: 3,
columns: 2,
buttons: [
ColoredButton(
PlayContentAction(
Expand Down Expand Up @@ -73,6 +73,82 @@ final bundle = Bundle(
),
Colors.red,
),
ColoredButton(
PlayContentAction(
Image(
Uri.parse('assets/heilshorn-cows.jpg'),
maxDuration: Duration(seconds: 2),
),
),
Colors.blue,
),
ColoredButton(
PlayContentAction(
Audio(
Uri.parse('assets/Farm-SoundBible.com-1720780826.opus'),
maxDuration: Duration(seconds: 2),
),
),
Colors.green,
),
ColoredButton(
PlayContentAction(
Playlist(
<Medium>[
Image(
Uri.parse('assets/heilshorn-cows.jpg'),
maxDuration: Duration(seconds: 2),
),
Image(
Uri.parse('assets/heilshorn-cows2.jpg'),
maxDuration: Duration(seconds: 2),
),
],
),
),
Colors.purple,
),
ColoredButton(
PlayContentAction(
Playlist(
<Medium>[
MultiMedium(
VisualizableMultiMediumTrack(
<Visualizable>[
Image(Uri.parse('assets/heilshorn-cows2.jpg'),
maxDuration: Duration(seconds: 2)),
],
),
backgroundTrack: AudibleBackgroundMultiMediumTrack(
<Audible>[
Audio(Uri.parse(
'assets/Farm-SoundBible.com-1720780826.opus')),
],
),
),
MultiMedium(
AudibleMultiMediumTrack(
<Audible>[
Audio(
Uri.parse('assets/Farm-SoundBible.com-1720780826.opus'),
maxDuration: Duration(seconds: 4)),
],
),
backgroundTrack: VisualizableBackgroundMultiMediumTrack(
<Visualizable>[
Image(Uri.parse('assets/heilshorn-cows.jpg')),
],
),
),
Image(
Uri.parse('assets/heilshorn-cows2.jpg'),
maxDuration: Duration(seconds: 2),
),
],
),
),
Colors.orange,
),
],
),
);
Expand Down
3 changes: 2 additions & 1 deletion example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ dependencies:
lunofono_bundle:
git:
url: https://github.com/lunofono/lunofono_bundle.git
ref: v1.x.x
ref: v0.1.0

dev_dependencies:
flutter_test:
Expand All @@ -28,3 +28,4 @@ flutter:
assets:
- assets/Farm-SoundBible.com-1720780826.opus
- assets/heilshorn-cows.jpg
- assets/heilshorn-cows2.jpg
92 changes: 3 additions & 89 deletions lib/src/media_player.dart
Original file line number Diff line number Diff line change
@@ -1,89 +1,3 @@
import 'package:flutter/material.dart';

import 'package:provider/provider.dart' show ChangeNotifierProvider, Consumer;

import 'package:lunofono_bundle/lunofono_bundle.dart' show MultiMedium;

import 'media_player/controller_registry.dart' show ControllerRegistry;
import 'media_player/multi_medium_controller.dart' show MultiMediumController;
import 'media_player/multi_medium_player.dart' show MultiMediumPlayer;

/// A media player widget.
///
/// The player can play a [MultiMedium] via [SingleMediumController] plug-ins
/// that are obtained via the [ControllerRegistry]. It handles the playing and
/// synchronization of the [multimedium.mainTrack] and
/// [multimedium.backgroundTrack] and also the asynchronous nature of the player
/// controllers, by showing a progress indicator while the media is loading, and
/// the media afterwards, or a [MediaPlayerError] if an error occurred.
///
/// If a medium is played for which there is no [SingleMediumController]
/// registered in the [ControllerRegistry], a [MediaPlayerError] will be shown
/// instead of that medium.
///
/// All the orchestration behind the scenes is performed by
/// a [MultiMediumController] that is provided via a [ChangeNotifierProvider].
class MediaPlayer extends StatelessWidget {
/// The medium to play by this player.
final MultiMedium multimedium;

/// The background color for this player.
final Color backgroundColor;

/// The action to perform when this player stops.
final void Function(BuildContext) onMediaStopped;

/// The [ControllerRegistry] to create [SingleMediumController]s.
final ControllerRegistry registry;

/// Constructs a new [MediaPlayer].
///
/// The player will play the [multimedium] with a background color
/// [backgroundColor] (or black if null is used). When the media stops
/// playing, either because it was played completely or because it was stopped
/// by the user, the [onMediaStopped] callback will be called (if non-null).
///
/// If a [registry] is provided, then it is used to create the controller for
/// the media inside the [multimedium]. Otherwise
/// [ControllerRegistry.instance] is used.
const MediaPlayer({
@required this.multimedium,
Color backgroundColor,
this.onMediaStopped,
this.registry,
Key key,
}) : assert(multimedium != null),
backgroundColor = backgroundColor ?? Colors.black,
super(key: key);

/// Builds the UI for this widget.
@override
Widget build(BuildContext context) =>
ChangeNotifierProvider<MultiMediumController>(
create: (context) => MultiMediumController(
multimedium,
registry ?? ControllerRegistry.instance,
onMediumFinished: onMediaStopped,
)..initialize(context),
child: Consumer<MultiMediumController>(
child: Material(
elevation: 0,
color: backgroundColor,
child: Center(
child: MultiMediumPlayer(),
),
),
builder: (context, model, child) {
return GestureDetector(
onTap: () {
// XXX: For now the stop reaction is hardcoded to the tap.
// Also we should handle errors in the pause()'s future
model.mainTrackController.pauseCurrent(context);
model.backgroundTrackController.pauseCurrent(context);
onMediaStopped?.call(context);
},
child: child,
);
}),
);
}
export 'media_player/multi_medium_player.dart' show MultiMediumPlayer;
export 'media_player/playlist_player.dart' show PlaylistPlayer;
export 'media_player/single_medium_player.dart' show SingleMediumPlayer;
2 changes: 1 addition & 1 deletion lib/src/media_player/controller_registry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ControllerRegistry
/// The global instance for the registry.
///
/// This instance is initialized with all known media controllers.
static final instance = ControllerRegistry.defaults();
static var instance = ControllerRegistry.defaults();

/// Constructs an empty controller registry.
ControllerRegistry();
Expand Down
28 changes: 28 additions & 0 deletions lib/src/media_player/media_progress_indicator.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:flutter/material.dart';

/// A progress indicator that shows what kind of media is loading.
///
/// If [isVisualizable] is true, a [Icons.local_movies] will be shown, otherwise
/// a [Icons.music_note] will be shown. A [CircularProgressIndicator] is always
/// shown in the back.
class MediaProgressIndicator extends StatelessWidget {
/// If true, a [Icons.local_movies] is shown, otherwise a [Icons.music_note].
final bool isVisualizable;

/// Constructs a [MediaProgressIndicator] setting if it's [visualizable].
const MediaProgressIndicator({@required bool visualizable})
: assert(visualizable != null),
isVisualizable = visualizable;

/// Builds the widget.
@override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.center,
children: <Widget>[
Icon(isVisualizable ? Icons.local_movies : Icons.music_note),
CircularProgressIndicator(),
],
);
}
}
Loading

0 comments on commit 40b4834

Please sign in to comment.