Skip to content

Commit

Permalink
changelog:
Browse files Browse the repository at this point in the history
added support for local / downloaded songs play
fixed "play all" button for playlists which have less than 20 songs
fixed remove User playlist feature
  • Loading branch information
gokadzev committed Jun 23, 2022
1 parent 3504007 commit f85e0d6
Show file tree
Hide file tree
Showing 11 changed files with 425 additions and 145 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
<p align="center">
Online Song Search :mag:<br>
Streaming Support :musical_note:<br>
Offline Download Support :arrow_down:<br>
Download Support :arrow_down:<br>
Play Local / Downloaded Songs Support :open_file_folder: <br>
High Quality mp3 Format :fire:<br>
Lyrics Support :pencil:<br>
Lyrics Support :pencil:<br>
No Ads :no_entry_sign:<br>
No Subscriptions :dollar:<br>

Expand Down
24 changes: 21 additions & 3 deletions lib/API/musify.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import 'package:musify/helper/mediaitem.dart';
import 'package:musify/services/audio_handler.dart';
import 'package:musify/services/audio_manager.dart';
import 'package:musify/services/data_manager.dart';
import 'package:on_audio_query/on_audio_query.dart';
import 'package:youtube_explode_dart/youtube_explode_dart.dart';

final yt = YoutubeExplode();
final OnAudioQuery _audioQuery = OnAudioQuery();

List ytplaylists = [];

Expand All @@ -20,6 +22,7 @@ List playlists = [];
List userPlaylists = [];
List userLikedSongsList = [];
List suggestedPlaylists = [];
List<SongModel> localSongs = [];

final lyrics = ValueNotifier<String>("null");
String _lastLyricsUrl = "";
Expand Down Expand Up @@ -160,9 +163,15 @@ Future getSongsFromPlaylist(playlistid) async {
setActivePlaylist(List plist) async {
List<MediaItem> activePlaylist = [];

for (var i = 0; i < 20; i++) {
final songUrl = await getSongUrl(plist[i]["ytid"]);
activePlaylist.add(mapToMediaItem(plist[i], songUrl));
if (plist is List<SongModel>) {
for (var song in plist) {
activePlaylist.add(songModelToMediaItem(song, song.data.toString()));
}
} else {
for (var i = 0; i < plist.length && i < 20; i++) {
final songUrl = await getSongUrl(plist[i]["ytid"]);
activePlaylist.add(mapToMediaItem(plist[i], songUrl));
}
}

MyAudioHandler().addQueueItems(activePlaylist);
Expand Down Expand Up @@ -211,6 +220,15 @@ Future getSongDetails(dynamic songIndex, dynamic songId) async {
);
}

getLocalSongs() async {
// DEFAULT:
// SongSortType.TITLE,
// OrderType.ASC_OR_SMALLER,
// UriType.EXTERNAL,
localSongs = await _audioQuery.querySongs();
return localSongs;
}

Future getSongLyrics(String artist, String title) async {
if (_lastLyricsUrl !=
'https://api.lyrics.ovh/v1/$artist/${title.split(" (")[0].split("|")[0].trim()}') {
Expand Down
12 changes: 12 additions & 0 deletions lib/helper/mediaitem.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:audio_service/audio_service.dart';
import 'package:on_audio_query/on_audio_query.dart';

Map mediaItemToMap(MediaItem mediaItem) {
return {
Expand All @@ -13,6 +14,17 @@ Map mediaItemToMap(MediaItem mediaItem) {
};
}

MediaItem songModelToMediaItem(SongModel song, String songUrl) {
return MediaItem(
id: song.id.toString(),
album: "",
artist: "",
title: song.displayName.toString(),
artUri: Uri.parse(""),
extras: {'url': songUrl, 'lowResImage': "", 'ytid': "", 'ogid': song.id},
);
}

MediaItem mapToMediaItem(Map song, String songUrl) {
return MediaItem(
id: song['id'].toString(),
Expand Down
1 change: 1 addition & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ GetIt getIt = GetIt.instance;

main() async {
await Hive.initFlutter();
await getLocalSongs();
await FlutterDownloader.initialize(
debug:
true, // optional: set to false to disable printing logs to console (default: true)
Expand Down
10 changes: 8 additions & 2 deletions lib/services/audio_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,14 @@ downloadSong(song) async {
}

Future<void> playSong(song) async {
final songUrl = await getSongUrl(song["ytid"]);
await MyAudioHandler().addQueueItem(mapToMediaItem(song, songUrl.toString()));
if (song["ytid"].length == 0) {
await MyAudioHandler()
.addQueueItem(mapToMediaItem(song, song["songUrl"].toString()));
} else {
final songUrl = await getSongUrl(song["ytid"]);
await MyAudioHandler()
.addQueueItem(mapToMediaItem(song, songUrl.toString()));
}
await play();
}

Expand Down
192 changes: 192 additions & 0 deletions lib/ui/localSongsPage.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:musify/API/musify.dart';
import 'package:musify/services/audio_manager.dart';
import 'package:musify/style/appColors.dart';

class LocalSongsPage extends StatelessWidget {
const LocalSongsPage({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
systemOverlayStyle:
const SystemUiOverlayStyle(statusBarBrightness: Brightness.dark),
centerTitle: true,
title: Text(
"Local Songs",
style: TextStyle(
color: accent,
fontSize: 25,
fontWeight: FontWeight.w700,
),
),
backgroundColor: Colors.transparent,
elevation: 0,
),
body: SingleChildScrollView(
child: Column(
children: [
Row(
children: [
Container(
margin: const EdgeInsets.only(left: 10.0, right: 10.0),
height: 200.0,
width: 200.0,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
color: Colors.transparent,
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
gradient: LinearGradient(
colors: [
accent.withAlpha(30),
Colors.white.withAlpha(30)
],
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
MdiIcons.download,
size: 30,
color: accent,
),
Text(
"Local Songs",
style: TextStyle(color: accent),
textAlign: TextAlign.center,
),
],
),
),
),
),
const SizedBox(width: 16.0),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 12.0),
Text(
"Local Songs",
style: TextStyle(
color: accent,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 16.0),
Text(
"Your downloaded songs here!",
style: TextStyle(
color: accent,
fontSize: 10,
fontWeight: FontWeight.w600,
),
),
const Padding(
padding: EdgeInsets.only(top: 5, bottom: 5),
),
TextButton(
onPressed: () => {
setActivePlaylist(localSongs),
},
style: TextButton.styleFrom(
backgroundColor: accent,
),
child: const Text(
"PLAY ALL",
style: TextStyle(color: Colors.white),
),
),
],
),
)
],
),
const Padding(padding: EdgeInsets.only(top: 20)),
ListView.builder(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
addAutomaticKeepAlives:
false, // may be problem with lazyload if it implemented
addRepaintBoundaries: false,
// Need to display a loading tile if more items are coming
itemCount: localSongs.length,
itemBuilder: (BuildContext context, int index) {
final lsong = {
"id": index,
"ytid": "",
"title": localSongs[index].displayName,
"image": "",
"lowResImage": "",
"highResImage": "",
"songUrl": localSongs[index].data,
"album": "",
"type": "song",
"more_info": {
"primary_artists": "",
"singers": "",
}
};

return Padding(
padding: const EdgeInsets.only(top: 5, bottom: 5),
child: Card(
color: Colors.black26,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
elevation: 0,
child: InkWell(
borderRadius: BorderRadius.circular(20.0),
onTap: () {
playSong(lsong);
},
splashColor: accent,
hoverColor: accent,
focusColor: accent,
highlightColor: accent,
child: Column(
children: <Widget>[
ListTile(
visualDensity: VisualDensity(vertical: 3),
leading: Padding(
padding: const EdgeInsets.only(
top: 8.0,
bottom: 8.0,
left: 8.0,
right: 25.0),
child: Icon(
MdiIcons.musicNoteOutline,
size: 30,
color: accent,
),
),
title: Text(
overflow: TextOverflow.ellipsis,
lsong['title'].toString(),
style: TextStyle(color: accent),
),
),
],
),
),
));
},
)
],
)),
);
}
}
Loading

0 comments on commit f85e0d6

Please sign in to comment.