MusicPlayer/lib/ui/music_player.dart

185 lines
4.9 KiB
Dart
Raw Normal View History

2022-03-24 09:57:55 +00:00
// ignore_for_file: avoid_print
2022-03-23 20:15:29 +00:00
import 'dart:math';
2022-03-23 20:27:05 +00:00
import 'dart:ui';
2022-03-23 20:15:29 +00:00
2022-03-24 09:57:55 +00:00
import 'package:audioplayers/audioplayers.dart';
2022-03-24 08:57:47 +00:00
import 'package:fluent_ui/fluent_ui.dart' as fluent;
2022-03-24 08:20:43 +00:00
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
2022-03-23 20:15:29 +00:00
import 'package:flutter/material.dart';
import 'package:music_web_player/api.dart';
import 'package:music_web_player/ui/cover_image.dart';
class MusicPlayer extends StatefulWidget {
final MusicsList musicsList;
const MusicPlayer({Key? key, required this.musicsList}) : super(key: key);
@override
State<MusicPlayer> createState() => _MusicPlayerState();
}
class _MusicPlayerState extends State<MusicPlayer> {
final rng = Random();
2022-03-24 09:57:55 +00:00
final audioPlayer = AudioPlayer(playerId: "player");
var _playerState = PlayerState.STOPPED;
2022-03-23 20:15:29 +00:00
final List<MusicEntry> stack = [];
int currMusicPos = 0;
MusicEntry get currMusic {
if (currMusicPos < 0) currMusicPos = 0;
// Automatically choose next music if required
if (currMusicPos >= stack.length) {
var nextId = rng.nextInt(widget.musicsList.length);
stack.add(widget.musicsList[nextId]);
}
return stack[currMusicPos];
}
2022-03-24 09:57:55 +00:00
@override
void initState() {
super.initState();
audioPlayer.onPlayerError.listen((event) {
print("Player error!");
print(event);
_playNext();
});
audioPlayer.onPlayerStateChanged
.listen((s) => setState(() => {_playerState = s}));
}
Future<void> _play() async {
if (_playerState == PlayerState.PAUSED) {
await audioPlayer.resume();
} else {
await audioPlayer.play(currMusic.musicURL);
}
}
Future<void> _stop() async {
await audioPlayer.stop();
}
void _pause() async {
await audioPlayer.pause();
}
void _playPrevious() async {
currMusicPos -= 1;
await _stop();
await _play();
}
void _playNext() async {
currMusicPos += 1;
await _stop();
await _play();
}
2022-03-23 20:15:29 +00:00
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) => Stack(
children: [
// Background image
CoverImage(
music: currMusic,
width: constraints.maxWidth,
height: constraints.maxHeight,
fit: BoxFit.cover,
),
2022-03-23 20:27:05 +00:00
ClipRRect(
// Clip it cleanly.
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Container(
2022-03-23 20:32:33 +00:00
color: Colors.black.withOpacity(0.8),
2022-03-23 20:27:05 +00:00
alignment: Alignment.center,
2022-03-23 20:32:33 +00:00
child: SizedBox(
width: constraints.maxWidth,
height: constraints.maxHeight,
),
2022-03-23 20:27:05 +00:00
),
)),
2022-03-24 08:20:43 +00:00
_buildCenter(),
2022-03-23 20:15:29 +00:00
],
),
);
}
2022-03-24 08:20:43 +00:00
Widget _buildCenter() {
2022-03-24 08:57:47 +00:00
return fluent.Center(
2022-03-24 09:57:55 +00:00
child: SizedBox(
2022-03-24 08:57:47 +00:00
width: 250,
2022-03-24 08:20:43 +00:00
child: Column(
2022-03-24 08:57:47 +00:00
mainAxisAlignment: fluent.MainAxisAlignment.center,
crossAxisAlignment: fluent.CrossAxisAlignment.center,
2022-03-24 08:20:43 +00:00
children: [
Material(
borderRadius: const BorderRadius.all(
Radius.circular(18.0),
),
clipBehavior: Clip.hardEdge,
child: CoverImage(
width: 250,
height: 250,
music: currMusic,
fit: BoxFit.cover,
backgroundColor: Colors.black12,
icon: const Icon(FluentIcons.music_note_2_24_regular, size: 90),
),
),
const SizedBox(height: 40),
2022-03-24 09:57:55 +00:00
Text(
currMusic.title,
style: const TextStyle(fontSize: 22),
textAlign: TextAlign.center,
2022-03-24 08:57:47 +00:00
),
2022-03-24 09:57:55 +00:00
const SizedBox(height: 20),
Text(currMusic.artist, textAlign: TextAlign.center),
2022-03-24 08:57:47 +00:00
const fluent.SizedBox(height: 40),
fluent.Row(
children: [
IconButton(
icon: const PlayerIcon(fluent.FluentIcons.previous),
2022-03-24 09:57:55 +00:00
onPressed: currMusicPos == 0 ? null : _playPrevious,
2022-03-24 08:57:47 +00:00
),
const Spacer(),
IconButton(
2022-03-24 09:57:55 +00:00
icon: PlayerIcon(_playerState == PlayerState.PLAYING
? fluent.FluentIcons.pause
: fluent.FluentIcons.play),
onPressed:
_playerState == PlayerState.PLAYING ? _pause : _play,
2022-03-24 08:57:47 +00:00
),
const Spacer(),
IconButton(
icon: const PlayerIcon(fluent.FluentIcons.next),
2022-03-24 09:57:55 +00:00
onPressed: _playNext,
2022-03-24 08:57:47 +00:00
),
],
)
2022-03-24 08:20:43 +00:00
],
),
),
);
2022-03-23 20:15:29 +00:00
}
}
2022-03-24 08:57:47 +00:00
class PlayerIcon extends StatelessWidget {
final IconData icon;
const PlayerIcon(this.icon, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => Icon(icon, size: 35);
}