Skip to content

Commit

Permalink
Merge pull request #131 from KRTirtho/audioplayers_integration
Browse files Browse the repository at this point in the history
Replaced `just_audio` with `audioplayers` & Refactored Playback provider
  • Loading branch information
KRTirtho authored Jul 3, 2022
2 parents 4321668 + 46d6f62 commit ae71412
Show file tree
Hide file tree
Showing 38 changed files with 1,077 additions and 883 deletions.
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"cmake.configureOnOpen": false
"cmake.configureOnOpen": false,
"cSpell.words": [
"Mpris"
]
}
19 changes: 13 additions & 6 deletions CONTRIBUTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@ All types of contributions are encouraged and valued. See the [Table of Contents
## Table of Contents

- [Code of Conduct](#code-of-conduct)
- [I Have a Question](#i-have-a-question)
- [I Want To Contribute](#i-want-to-contribute)
- [Reporting Bugs](#reporting-bugs)
- [Suggesting Enhancements](#suggesting-enhancements)
- [Your First Code Contribution](#your-first-code-contribution)
- [Contributing to Spotube](#contributing-to-spotube)
- [Table of Contents](#table-of-contents)
- [Code of Conduct](#code-of-conduct)
- [I Have a Question](#i-have-a-question)
- [I Want To Contribute](#i-want-to-contribute)
- [Reporting Bugs](#reporting-bugs)
- [Before Submitting a Bug Report](#before-submitting-a-bug-report)
- [How Do I Submit a Good Bug Report?](#how-do-i-submit-a-good-bug-report)
- [Suggesting Enhancements](#suggesting-enhancements)
- [Your First Code Contribution](#your-first-code-contribution)


## Code of Conduct
Expand Down Expand Up @@ -109,6 +113,9 @@ Enhancement suggestions are tracked as [GitHub issues](https://github.com/KRTirt

### Your First Code Contribution

<!-- Download -->
audioplayers requirement https://github.com/bluefireteam/audioplayers/blob/main/packages/audioplayers_linux/requirements.md

Do the following:
- Download the latest Flutter SDK (>=2.15.1) & enable desktop support
- Install Development dependencies in linux
Expand Down
14 changes: 6 additions & 8 deletions lib/components/Album/AlbumCard.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ class AlbumCard extends HookConsumerWidget {
@override
Widget build(BuildContext context, ref) {
Playback playback = ref.watch(playbackProvider);
bool isPlaylistPlaying = playback.currentPlaylist != null &&
playback.currentPlaylist!.id == album.id;
bool isPlaylistPlaying =
playback.playlist != null && playback.playlist!.id == album.id;
final int marginH =
useBreakpointValue(sm: 10, md: 15, lg: 20, xl: 20, xxl: 20);
return PlaybuttonCard(
imageUrl: imageToUrlString(album.images),
margin: EdgeInsets.symmetric(horizontal: marginH.toDouble()),
isPlaying: playback.currentPlaylist?.id != null &&
playback.currentPlaylist?.id == album.id,
isPlaying:
playback.playlist?.id != null && playback.playlist?.id == album.id,
title: album.name!,
description:
"Album • ${artistsToString<ArtistSimple>(album.artists ?? [])}",
Expand All @@ -41,14 +41,12 @@ class AlbumCard extends HookConsumerWidget {
.toList();
if (tracks.isEmpty) return;

playback.setCurrentPlaylist = CurrentPlaylist(
await playback.playPlaylist(CurrentPlaylist(
tracks: tracks,
id: album.id!,
name: album.name!,
thumbnail: album.images!.first.url!,
);
playback.setCurrentTrack = tracks.first;
await playback.startPlaying();
));
},
);
}
Expand Down
28 changes: 14 additions & 14 deletions lib/components/Album/AlbumView.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/components/Shared/HeartButton.dart';
Expand All @@ -18,24 +17,25 @@ class AlbumView extends HookConsumerWidget {
final AlbumSimple album;
const AlbumView(this.album, {Key? key}) : super(key: key);

playPlaylist(Playback playback, List<Track> tracks,
Future<void> playPlaylist(Playback playback, List<Track> tracks,
{Track? currentTrack}) async {
currentTrack ??= tracks.first;
var isPlaylistPlaying = playback.currentPlaylist?.id == album.id;
final isPlaylistPlaying = playback.playlist?.id == album.id;
if (!isPlaylistPlaying) {
playback.setCurrentPlaylist = CurrentPlaylist(
tracks: tracks,
id: album.id!,
name: album.name!,
thumbnail: imageToUrlString(album.images),
await playback.playPlaylist(
CurrentPlaylist(
tracks: tracks,
id: album.id!,
name: album.name!,
thumbnail: imageToUrlString(album.images),
),
tracks.indexWhere((s) => s.id == currentTrack?.id),
);
playback.setCurrentTrack = currentTrack;
} else if (isPlaylistPlaying &&
currentTrack.id != null &&
currentTrack.id != playback.currentTrack?.id) {
playback.setCurrentTrack = currentTrack;
currentTrack.id != playback.track?.id) {
await playback.play(currentTrack);
}
await playback.startPlaying();
}

@override
Expand All @@ -54,8 +54,8 @@ class AlbumView extends HookConsumerWidget {

return TrackCollectionView(
id: album.id!,
isPlaying: playback.currentPlaylist?.id != null &&
playback.currentPlaylist?.id == album.id,
isPlaying:
playback.playlist?.id != null && playback.playlist?.id == album.id,
title: album.name!,
titleImage: albumArt,
tracksSnapshot: tracksSnapshot,
Expand Down
21 changes: 11 additions & 10 deletions lib/components/Artist/ArtistProfile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -183,24 +183,25 @@ class ArtistProfile extends HookConsumerWidget {
topTracksSnapshot.when(
data: (topTracks) {
final isPlaylistPlaying =
playback.currentPlaylist?.id == data.id;
playback.playlist?.id == data.id;
playPlaylist(List<Track> tracks,
{Track? currentTrack}) async {
currentTrack ??= tracks.first;
if (!isPlaylistPlaying) {
playback.setCurrentPlaylist = CurrentPlaylist(
tracks: tracks,
id: data.id!,
name: "${data.name!} To Tracks",
thumbnail: imageToUrlString(data.images),
await playback.playPlaylist(
CurrentPlaylist(
tracks: tracks,
id: data.id!,
name: "${data.name!} To Tracks",
thumbnail: imageToUrlString(data.images),
),
tracks.indexWhere((s) => s.id == currentTrack?.id),
);
playback.setCurrentTrack = currentTrack;
} else if (isPlaylistPlaying &&
currentTrack.id != null &&
currentTrack.id != playback.currentTrack?.id) {
playback.setCurrentTrack = currentTrack;
currentTrack.id != playback.track?.id) {
await playback.play(currentTrack);
}
await playback.startPlaying();
}

return Column(children: [
Expand Down
8 changes: 4 additions & 4 deletions lib/components/Lyrics/Lyrics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ class Lyrics extends HookConsumerWidget {
children: [
Center(
child: Text(
playback.currentTrack?.name ?? "",
playback.track?.name ?? "",
style: breakpoint >= Breakpoints.md
? textTheme.headline3
: textTheme.headline4?.copyWith(fontSize: 25),
),
),
Center(
child: Text(
artistsToString<Artist>(playback.currentTrack?.artists ?? []),
artistsToString<Artist>(playback.track?.artists ?? []),
style: breakpoint >= Breakpoints.md
? textTheme.headline5
: textTheme.headline6,
Expand All @@ -45,15 +45,15 @@ class Lyrics extends HookConsumerWidget {
child: geniusLyricsSnapshot.when(
data: (lyrics) {
return Text(
lyrics == null && playback.currentTrack == null
lyrics == null && playback.track == null
? "No Track being played currently"
: lyrics!,
style: textTheme.headline6
?.copyWith(color: textTheme.headline1?.color),
);
},
error: (error, __) => Text(
"Sorry, no Lyrics were found for `${playback.currentTrack?.name}` :'("),
"Sorry, no Lyrics were found for `${playback.track?.name}` :'("),
loading: () => const ShimmerLyrics(),
),
),
Expand Down
14 changes: 7 additions & 7 deletions lib/components/Lyrics/SyncedLyrics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class SyncedLyrics extends HookConsumerWidget {
controller.scrollToIndex(0);
failed.value = false;
return null;
}, [playback.currentTrack]);
}, [playback.track]);

useEffect(() {
if (lyricValue != null && lyricValue.rating <= 2) {
Expand Down Expand Up @@ -99,20 +99,20 @@ class SyncedLyrics extends HookConsumerWidget {
Center(
child: SizedBox(
height: breakpoint >= Breakpoints.md ? 50 : 30,
child: playback.currentTrack?.name != null &&
playback.currentTrack!.name!.length > 29
child: playback.track?.name != null &&
playback.track!.name!.length > 29
? SpotubeMarqueeText(
text: playback.currentTrack?.name ?? "Not Playing",
text: playback.track?.name ?? "Not Playing",
style: headlineTextStyle,
)
: Text(
playback.currentTrack?.name ?? "Not Playing",
playback.track?.name ?? "Not Playing",
style: headlineTextStyle,
),
)),
Center(
child: Text(
artistsToString<Artist>(playback.currentTrack?.artists ?? []),
artistsToString<Artist>(playback.track?.artists ?? []),
style: breakpoint >= Breakpoints.md
? textTheme.headline5
: textTheme.headline6,
Expand Down Expand Up @@ -157,7 +157,7 @@ class SyncedLyrics extends HookConsumerWidget {
},
),
),
if (playback.currentTrack != null &&
if (playback.track != null &&
(lyricValue == null || lyricValue.lyrics.isEmpty == true))
const Expanded(child: ShimmerLyrics()),
],
Expand Down
81 changes: 28 additions & 53 deletions lib/components/Player/Player.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import 'dart:async';

import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:spotube/components/Player/PlayerActions.dart';
import 'package:spotube/components/Player/PlayerOverlay.dart';
import 'package:spotube/components/Player/PlayerTrackDetails.dart';
import 'package:spotube/components/Player/PlayerControls.dart';
import 'package:spotube/helpers/image-to-url-string.dart';
import 'package:spotube/hooks/useBreakpoints.dart';
import 'package:spotube/models/LocalStorageKeys.dart';
import 'package:spotube/models/Logger.dart';
import 'package:spotube/provider/Playback.dart';
import 'package:flutter/material.dart';
import 'package:spotube/utils/AudioPlayerHandler.dart';

class Player extends HookConsumerWidget {
Player({Key? key}) : super(key: key);
Expand All @@ -23,41 +18,14 @@ class Player extends HookConsumerWidget {
Widget build(BuildContext context, ref) {
Playback playback = ref.watch(playbackProvider);

final _volume = useState(0.0);

final breakpoint = useBreakpoints();

final AudioPlayerHandler player = playback.player;

final Future<SharedPreferences> future =
useMemoized(SharedPreferences.getInstance);
final AsyncSnapshot<SharedPreferences?> localStorage =
useFuture(future, initialData: null);

useEffect(() {
/// warm up the audio player before playing actual audio
/// It's for resolving unresolved issue related to just_audio's
/// [disposeAllPlayers] method which is throwing
/// [UnimplementedException] in the [PlatformInterface]
/// implementation
player.core.setAsset("assets/warmer.mp3");
return null;
}, []);

useEffect(() {
if (localStorage.hasData) {
_volume.value = localStorage.data?.getDouble(LocalStorageKeys.volume) ??
player.core.volume;
}
return null;
}, [localStorage.data]);

String albumArt = useMemoized(
() => imageToUrlString(
playback.currentTrack?.album?.images,
index: (playback.currentTrack?.album?.images?.length ?? 1) - 1,
playback.track?.album?.images,
index: (playback.track?.album?.images?.length ?? 1) - 1,
),
[playback.currentTrack?.album?.images],
[playback.track?.album?.images],
);

final entryRef = useRef<OverlayEntry?>(null);
Expand All @@ -82,7 +50,7 @@ class Player extends HookConsumerWidget {
// entry will result in splashing while resizing the window
if (breakpoint.isLessThanOrEqualTo(Breakpoints.md) &&
entryRef.value == null &&
playback.currentTrack != null) {
playback.track != null) {
entryRef.value = OverlayEntry(
opaque: false,
builder: (context) => PlayerOverlay(albumArt: albumArt),
Expand All @@ -104,7 +72,7 @@ class Player extends HookConsumerWidget {
return () {
disposeOverlay();
};
}, [breakpoint, playback.currentTrack]);
}, [breakpoint, playback.track]);

// returning an empty non spacious Container as the overlay will take
// place in the global overlay stack aka [_entries]
Expand Down Expand Up @@ -135,22 +103,29 @@ class Player extends HookConsumerWidget {
Container(
height: 20,
constraints: const BoxConstraints(maxWidth: 200),
child: Slider.adaptive(
value: _volume.value,
onChanged: (value) async {
try {
await player.core.setVolume(value).then((_) {
_volume.value = value;
localStorage.data?.setDouble(
LocalStorageKeys.volume,
value,
);
});
} catch (e, stack) {
logger.e("onChange", e, stack);
}
},
),
child: HookBuilder(builder: (context) {
final volume = useState(
useMemoized(() => playback.volume, []),
);
return Slider.adaptive(
min: 0,
max: 1,
value: volume.value,
onChanged: (v) {
volume.value = v;
},
onChangeEnd: (value) async {
try {
// You don't really need to know why but this
// way it works only
await playback.setVolume(value);
await playback.setVolume(value);
} catch (e, stack) {
logger.e("onChange", e, stack);
}
},
);
}),
),
PlayerActions()
],
Expand Down
Loading

0 comments on commit ae71412

Please sign in to comment.