An open-source non-commercial music player built with Flutter
For the time being it's Android-only and I have no plans to support other platforms, however I don't mind accepting someone's PR tweaking this
Music player built with Flutter
License: BSD 3-Clause "New" or "Revised" License
An open-source non-commercial music player built with Flutter
For the time being it's Android-only and I have no plans to support other platforms, however I don't mind accepting someone's PR tweaking this
Currently this is not implemented, because we use itemExtent
.
We must use it:
Otherwise it's just very laggy.
However, itemExtent
is broken for ReordableList flutter/flutter#84901
So it poses a dilemma, where we can only use one or another.
I tried digging this, but it seems that the issue is deeply in the underlying SliverFixedExtentList, which lays all of its children with the fixed extent height. ReordableList inserts an empty box when moving a child, which in this protocol means that extra space will appear.
The solution could involve either
This is a cat in a bag option.
AFAIK this package uses techniques from native RecyclerView Android implementation, which allows for reordering, fast jumping to particular item, even if the list is not of fixed height, and other cool features.
But this is an unexplored third party dependency that could potentially become unmaintained, or just containt bugs we don't know of.
Come up with some hack, for example: in selection the list is changed to ReordableList without itemExtent and then changed back to a regular one when selection ends.
The main problem here is to decide how it should work.
It opens an independent Sweyer instance in a separate activity, with a separate audio_service
and player. The main app still could be launched and interfere with the playback of a standalone one.
I already experimented with a UI for this feature, which I kept unifinished under a StandalonePlayer
class.
This breaks the paradigm of accesing all the content through the MediaStore.
In its turn, this leads to the uncertainty of what we should do with the queue, as a major problem, but certainly not limited.
But this example poses a deeper thought of how we should handle a case with different song sources in the future.
It's very likely this could happen.
For example, if the app becomes a Spotfiy/YT music/whatever else client.
Should the queue be united and allow multiple sources of songs?
Should it fundamentally allow only one source in it?
Something else?
Answering these questions should be done very carefully, since this is a major architechtural decision and could inflict very big problems down the road, if not done right.
For example YT music doesn't allow you mixing local and non-local songs.
Currently it is possible to select only one playlist to add songs to.
Allow to select multiple playlists in a dialog.
Should use ContentSelectionController.createAlwaysInSelection
.
Slider events can fire unexpectedly sometimes
Related to flutter/flutter#28115
The issue will be gone if try to put route out of page view controller (or tabs controller, or any kind of gesture detecting widget)
When first launched the app scans filesystem for music. 90% of mp3 files on my phone are automatic call recordings. I wish it was possible to exclude some folders, manually or, even better, automatically.
For example, on my phone recordings are stored in /MIUI/sound_recorder
Now that Flutter's stretching overscroll seems really on-par with the native implementation, we can consider enabling it from the relevant API 31 level. Or just on all of them.
https://developer.android.com/guide/topics/resources/app-languages#app-language-settings
In the meantime we can hardcode it, or implement ourselves
The app looks amazing but is still missing some implementations :
I know its non commercial as you stated in the Readme but these features will make the app more reachable to wider range of audience
All deselected, therefore selection closes
Nothing happens
1.0.9
No response
A place for a general discussion about developing the new version.
I also created a project to better keep track of what is being done.
cc @Abestanis feel free to write any other plans that you have,
you have been contributing a lot recently, don't forget to take a rest :-)
I'm making a music player in Finamp and was interested with how you implement your track panel. Currently, I'm just using a list tile as the bottom nav bar on each page that needs it, but that has the issue of the track panel being duplicated across pages and it obviously fading in with the rest of the page. It also doesn't have the nice swipe gesture and effect. Using multiple navigators sort of works but now the drawer doesn't go over the bar (which yours does). I've looked at the source code of Sweyer and I can't figure out the general layout of how everything works.
I'm not asking for code-level help by the way, just a general overview is enough :)
Given that most people would probably like to fill a newly created playlist with songs, the Add to playlist
screen should automatically open for the new playlist after the user clicks Create
in the naming dialog.
There are two issues:
X
, which indicates that pressing it should close the notification. Instead, it only closes the media session and on newer Android version, the notification stays visible by default, when the media session ends. The user has to explicitly configure the notification to close, as shown in the gif. I propose that the icon should change to a square ⏹
, which would make the stopping intent clear and prevent the confusion.Currently we display all content in one fixed way.
Consider allowing users to choose between these variants for all kinds of content (maybe with exception of songs):
Add new content type - genres.
Would be a cool addition if we could also fetch genre images from Genius, as we already do for artists.
It seems like Codecov itself is working correctly
https://app.codecov.io/gh/nt4f04uNd/sweyer/tree/master/lib/logic
But I the repo settings, under a Webhooks
section I found that there's some webhook, which I didn't create and it is somehow related to the Codecov.
https://github.com/nt4f04uNd/sweyer/settings/hooks/357895302
It calls into https://codecov.io/webhooks/github
, but all of the responses are just 403
No error on startup.
The following error is thrown:
----------------FIREBASE CRASHLYTICS----------------
I/flutter (16104): Null check operator used on a null value
I/flutter (16104): #0 ScrollPosition.minScrollExtent (package:flutter/src/widgets/scroll_position.dart:139:49)
I/flutter (16104): #1 _QueueTabState.scrollToSong (package:sweyer/routes/home_route/player_route.dart:236:43)
I/flutter (16104): #2 _QueueTabState.initState.<anonymous closure> (package:sweyer/routes/home_route/player_route.dart:216:15)
I/flutter (16104): #3 _QueueTabState.initState.<anonymous closure> (package:sweyer/routes/home_route/player_route.dart:210:76)
I/flutter (16104): #4 _rootRunUnary (dart:async/zone.dart:1434:47)
I/flutter (16104): #5 _CustomZone.runUnary (dart:async/zone.dart:1335:19)
I/flutter (16104): #6 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
I/flutter (16104): #7 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
I/flutter (16104): #8 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
I/flutter (16104): #9 _SyncBroadcastStreamController._sendData (dart:async/broadcast_stream_controller.dart:377:25)
I/flutter (16104): #10 _BroadcastStreamController.add (dart:async/broadcast_stream_controller.dart:244:5)
I/flutter (16104): #11 _StartWithStreamSink._safeAddFirstEvent (package:rxdart/src/t
A simple fix would be to check scrollController.position.hasContentDimensions
before, but I'm wondering if this is maybe just the symptom of an inverted if condition here:
sweyer/lib/routes/home_route/player_route.dart
Lines 214 to 217 in 93b5bdf
I have two questions about this, @nt4f04uNd:
Was the intention of this to scroll to the currently playing song in the queue view when the user is looking at it?
Latest on the 1.0.8
branch; 93b5bdf
No response
Dialog closed
Dialog closed, but selection as well
1.0.9
No response
KEYCODE_MEDIA_PLAY
event or KEYCODE_MEDIA_PLAY_PAUSE
event, e.g. press the play button on a connected headset.The app should be able to start from the audio_service
and start playing audio.
The app does start in the background, but never plays audio. This is because the following error is thrown:
I/System.out: ### onAttachedToEngine
I/System.out: ### 1 client handlers
I/System.out: ### new AudioHandlerInterface
I/System.out: ### connect
D/MediaBrowserCompat: Connecting to a MediaBrowserService.
I/System.out: ### connect returned
I/System.out: ### onAttachedToEngine completed
D/DeviceInfoPlugin: Use TaskQueues.
I/System.out: flutterEngine warmed up
I/System.out: ### onStartCommand
I/System.out: ### onMediaButtonEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_MEDIA_PLAY_PAUSE, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=0, downTime=0, deviceId=-1, source=0x0, displayId=0 }
2022-06-26 17:39:10.733 6154-6154/com.nt4f04und.sweyer I/System.out: ### listener = com.ryanheise.audioservice.AudioServicePlugin$AudioHandlerInterface@8194acc
I/System.out: ### calling onClick
I/System.out: ### sending click map: {button=0}
I/System.out: ### called onClick
I/System.out: ### onGetRoot. isRecentRequest=false
I/System.out: ### onConnected
I/System.out: ### registered mediaController callback
I/System.out: ### onConnected returned
I/flutter: The Dart VM service is listening on http://127.0.0.1:45025/VEcJ_HFwVvI=/
I/flutter: ----------------FIREBASE CRASHLYTICS----------------
I/flutter: MissingPluginException(No implementation found for method retrieveSongs on channel content_channel)
I/flutter: #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:165:7)
<asynchronous suspension>
#1 MethodChannel.invokeListMethod (package:flutter/src/services/platform_channel.dart:353:35)
<asynchronous suspension>
#2 ContentChannel.retrieveSongs (package:sweyer/logic/player/content_channel.dart:113:18)
<asynchronous suspension>
#3 ContentControl.refetch.<anonymous closure> (package:sweyer/logic/player/content.dart:444:33)
<asynchronous suspension>
#4 ContentControl.refetch (package:sweyer/logic/player/content.dart:441:5)
<asynchronous suspension>
#5 Future.wait.<anonymous closure> (dart:async/future.dart:521:21)
<asynchronous suspension>
#6 Future.any.onValue (dart:async/future.dart:611:5)
<asynchronous suspension>
The reason for the error is that ContentChannel
initialization is triggered by MainActivity.onCreate
, but when the app is not running and we are starting via the audio service, no MainActivity
is ever created and therefore the MethodChannel
is never registered.
The only workaround I found (suggested by ryanheise/audio_service#399 (comment)) is to extract the method channel into a separate plugin and use the plugin registration system to initialize the method channel under all conditions.
@nt4f04uNd do you have a better idea how to approach this?
Latest on the 1.0.8
branch; c6386e6
No response
Integrate the app with the Google assitant commands.
This shouldn't require writing any new playback code, since AFAIK all it does is it calls into audio_service
methods.
But for this the app should somehow expose itself for the Google assistant to know of it and be able to interact with it. Currently this doesn't work.
There are multiple features that are a non-trivial time investment to implement and get the author of the library to review and merge them, because they invlove writing and testing the code for multiple platforms, and both me and the author have other stuff to do.
From the top of my head, those are the most imporant ones:
The entire diff between the fork and the latest audio_service
version can be seen here https://github.com/ryanheise/audio_service/compare/minor...nt4f04uNd:audio_service:sweyer?expand=1
Using the fork prevents us from getting the latest changes from the library and will eventually become so stale, I will either have to cherry-pick new changes into it, or be forced to implement those features.
File google-services.json is missing. The Google Services Plugin cannot function without it. i am trying to run this application in my visual studio code but missing one file
Either
Or
For the app to start.
We just hang forever because we throw an exception here
sweyer/lib/logic/models/album.dart
Line 103 in 7496517
sweyer/lib/logic/models/album.dart
Line 104 in 7496517
The value for fistYear
and lastYear
seem to be null
for at least one album, so the cast to int
fails.
We should:
lastYear
already is, we just need to change the cast).I would love to submit a MR so we can patch this as soon as possible (I think this deserves a hot fix release), but I'm on vacation for a week so I won't be able to work on it until I'm back.
1.0.10
14
Hey im trying to run your app is not working
what im doing wrong
flutter doctor
[✓] Flutter (Channel stable, 2.2.2, on macOS 11.1 20C69 darwin-x64, locale
en-GB)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Xcode - develop for iOS and macOS
[✗] Chrome - develop for the web (Cannot find Chrome executable at
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome)
! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.
[✓] Android Studio (version 4.1)
[✓] VS Code (version 1.57.1)
[✓] Connected device (2 available)
! Doctor found issues in 1 category.
System UI white/adaptive colors
System UI has gray colors, which are poorly visible
1.0.9
No response
Here are screencasts of a new animated splash screen from Telegram.
And screencasts from Sweyer.
I checked other apps, and those that don't support new splash screen all look a bit pixelated.
We should support the new splash screen.
App crashes when open android 10, app version latest 1.0.4
Populating the app with more languages is easy.
Please read the entire documentation - this will take no more than 10 minutes of your time, but will make the process much easier for you and me.
As well as help creating the best version of the translation :-)
Android Playlist API was deprected
There are a lot of problems with this backend, it barely works.
You can create and read playlist, but everything other than that is extremely laggy and sometimes, more often than not, doesn't work:
I was aware of this problem at the moment of implementing this, but thought this was still worth using it, since these playlists are shared through the MediaStore.
While this is true, this is worth almost nothing, given how broken they are.
We should move on to some other implementations, probably file based.
MediaQuery.textScaleFactor >= 1.1
)There should be no layout issues.
The height given for the SongTitle
widget is not enough to contain the two lines of text. This is because kSongTileHeight
doesn't take the textScaleFactor
into account.
Additionally, the tab header widget on the bottom is partially hidden behind the bottom sheet.
For context, the default font size setting on my phone produces a textScaleFactor
of 1.1
. The old version of Sweyer (1.0.7
) does not have this problem.
Latest on the 1.0.8
branch; 4460b5a
No response
The current situation with dependency injection is rather horrible.
App should be rewritten with DI in mind.
Currently app mostly uses singletones as a main architecture solution, which was a bad decision in the hindsight. There aren't a lot of business logic classes, so the problem might not be immediately obvious:
A good option for a DI, which I personally like is riverpod.
It is easy, flexible, scalable, easily mockable and doesn't force you into doing some sketchy things, like for example Provider does by forcing you to tie your dependencies to a widget tree.
This is unexpected behavior, I would have expected the queue screen and player screen to close and no song to play.
The app just freezes for a second and then re-adds every track.
Have a button to view/copy all the information about content.
No editing (yet?), since this a questionable feature: very big effort, very scarce usage.
To see music and to be able to grant the app access to it.
The app does not have access to the music.
1.0.8
Android 13
Currently it is not possible to add a localisation in a way that all translated text is displayed correctly for the new language.
There are two problems:
1 lied
, Correct: 1 Lied
)areYouSureYouWantTo
, where the action is added at the end. This won't work for all languages.A reason for this current state is that many strings can be reused this way in English, but it takes away the flexibility needed for translation. As an example, currently we have the following situation:
Key | English |
---|---|
delete |
Delete |
tracksPlural |
{count,plural, =0{Tracks}=1{Track}=2{Tracks}few{Tracks}many{Tracks}other{Tracks}} |
playlistsPlural |
{count,plural, =0{Playlists}=1{Playlist}=2{Playlists}few{Playlists}many{Playlists}other{Playlists}} |
These are combined in
sweyer/lib/widgets/selection.dart
Line 1849 in 5e18cda
The only solution I can see is to create specialized versions of all strings. We would have to keeping the original ones, if they are used somewhere else. In the example above, we would end up with:
Key | English |
---|---|
delete |
Delete |
tracksPlural |
{count,plural, =0{Tracks}=1{Track}=2{Tracks}few{Tracks}many{Tracks}other{Tracks}} |
playlistsPlural |
{count,plural, =0{Playlists}=1{Playlist}=2{Playlists}few{Playlists}many{Playlists}other{Playlists}} |
deleteTracks |
{count, plural, =1{Delete track} other{Delete {count} tracks}} |
deletePlaylists |
{count, plural, =1{Delete playlist} other{Delete {count} playlists}} |
This way, the translator can change the case and positioning of everything.
Do you see any better alternative? I'm willing to put in some time to change this, if you approve.
Consider using NUMBER_OF_SONGS_FOR_ARTIST to show the number of tracks by the main artist on this album.
Maybe only show it when it's not equal to the NUMBER_OF_SONGS.
can you add backend as a flutter
When the user drags the scroll bar of the content lists (Tracks, Albums, Playlists and Artists) we show a label if the sorting is set to name or title.
This is a cool feature, but it is very hard to get to, because the scroll bar is only a few pixels wide. Additionally, to provide this feature we are keeping a copy of the Scrollbar code from Flutter, which requires us to manually keep it up to date with the Flutter implementation to get improvements and to keep compatible with changes in the framework.
I want to get your feedback on an alternative solution to this problem that does not require us to keep a slightly modified version of the code and makes the feature easier to access:
Instead of only showing the label when the scrollbar is dragged, show it when a scrolling from a drag, while the touchpoint of the drag is close to the window border on the scrollbar side. For the picture above, this would mean when dragging the list close to the right side of the screen, the labels would show up.
We can implement this using a NotificationListener<ScrollNotification>
and the dragDetails?.localPosition
of ScrollStartNotification
& ScrollUpdateNotification
.
I would like to implement this, if you are ok with it, @nt4f04uNd.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.