file_selector
네이티브 파일 선택 UI를 사용하여 파일을 열고 저장하거나 디렉터리를 선택하는 Flutter 플러그인.
Ubuntu, MacOs 및 곧 Android용 음악, 라디오, 텔레비전 및 팟캐스트 플레이어
네이티브 파일 선택 UI를 사용하여 파일을 열고 저장하거나 디렉터리를 선택하는 Flutter 플러그인.
리눅스에서 XDG 디렉터리 구성 정보를 읽기 위한 다트 패키지입니다.
Drift는 Dart 및 Flutter 애플리케이션에서 관계형 데이터를 저장하기 위한 반응형 라이브러리입니다.
drift 사용자를 위한 개발용 종속성입니다. 생성기 및 개발 도구를 포함합니다.
Flutter 앱에서 플랫폼 간에 쉽게 드리프트 데이터베이스를 설정할 수 있습니다.
v3.0.0패키지는 Flutter 프로젝트에 샤이머 효과를 쉽게 추가할 수 있는 방법을 제공합니다
v1.2.6Flutter 및 Dart용 크로스 플랫폼 비디오 플레이어 및 오디오 플레이어입니다. 성능이 뛰어나며 안정적이고 기능이 풍부하며 모듈식입니다.
패키지: media_kit에서 비디오 재생을 위한 네이티브 구현.
v0.18.18화면이 꺼져 있는 동안 백그라운드에서 오디오를 재생하기 위한 Flutter 플러그인입니다.
Mockito를 영감받아 만든 모크 프레임워크로, 페이크, 모크, 동작 검증 및 스텁 설정을 위한 API를 제공합니다.
FFI를 사용하여 Dart에서 일반적인 Windows API를 직접 호출합니다.
Flutter용 일반 캐시 매니저. 웹 파일을 장치의 스토리지에 저장하고, sqflite를 사용하여 캐시 정보를 저장합니다.
^1.7.1^0.18.18{"git":{"url":"https://github.com/Feichtmeier/audio-service-mpris","ref":"694a519007cf0a7b81d17ef3792cc157990a3dc8"}}^0.0.3^5.8.2^4.9.0^1.2.0^1.19.1^1.0.9^0.7.1^5.9.2^2.33.0^0.3.0^7.0.1^11.0.2^1.1.0^0.9.4^3.8.0{"sdk":"flutter"}^2.1.2{"sdk":"flutter"}^0.7.7+1^1.43.0^0.17.2^1.0.1^9.25.0^14.8.1^2.1.0^0.4.2^3.0.0^3.0.2^0.20.2^0.0.6^0.0.4^0.1.6^1.0.2^1.0.3{"git":{"url":"https://github.com/Predidit/media-kit.git","ref":"df5a969e617a1ce038d5cca46bedcfa1970a7dc6","path":"./media_kit"}}{"git":{"url":"https://github.com/Predidit/media-kit.git","ref":"df5a969e617a1ce038d5cca46bedcfa1970a7dc6","path":"./libs/universal/media_kit_libs_video"}}{"git":{"url":"https://github.com/Predidit/media-kit.git","ref":"df5a969e617a1ce038d5cca46bedcfa1970a7dc6","path":"./media_kit_video"}}^2.0.0^5.6.4^0.4.0^8.3.1^1.9.1^2.1.5^12.0.1{"git":{"url":"https://github.com/ubuntu-flutter-community/phoenix_theme","ref":"bb2637c5929aedcb8b65f66b99da9276951bf291"}}^1.1.0^0.7.15^2.0.0+1^0.4.0+1^3.0.1^2.5.5^4.0.0^3.4.0^3.2.0^6.3.2^5.15.0^0.5.1^1.1.0^9.0.1^0.2.2^0.2.2^2.15.0^2.33.0^0.14.4^6.0.0{"sdk":"flutter"}아래는 영문 원문 스냅샷입니다. 최신 내용은 GitHub에서 확인하세요.
MusicPod is a local music, radio, television and podcast player for Linux Desktop, MacOS and Windows (currently the metadata loading for local audio takes ages, so the Windows version is not considered stable if you are looking for the local audio feature. See #264 ). (Android is planed but no ETA yet when it will happen.)
| OS | How to install |
|---|---|
| Linux | Get it from the Snap Store or https://flathub.org/api/badge?locale=en or (Arch Linux) install from archlinuxcn via sudo pacman -S musicpod |
| Windows | Release Page |
| MacOS | Release Page |
| Android | WIP |
| Features | Dark Linux | Light Linux | Dark MacOS | Light MacOS |
|---|---|---|---|---|
| Play local audio | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/album_dark_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/album_light_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/album_dark_macos.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/album_light_macos.png |
| Find local audios sorted by Metadata | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/albums_dark_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/albums_light_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/albums_dark_macos.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/albums_light_macos.png |
| Play radio stations, with icytags and artwork looked up! | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/station_dark_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/station_light_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/station_dark_macos.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/station_light_macos.png |
| Play and download podcasts, safe progress, sort episodes and more! | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/podcast_dark_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/podcast_light_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/podcast_dark_macos.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/podcast_light_macos.png |
| Video podcast support! | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/video_dark_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/video_light_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/video_dark_macos.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/video_light_macos.png |
| Discover podcasts, filtered as you like | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/podcasts_dark_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/podcasts_light_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/podcasts_dark_macos.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/podcasts_light_macos.png |
| Discover radio stations, filtered as you like | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/radio_dark_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/radio_light_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/radio_dark_macos.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/radio_light_macos.png |
| Different view modes | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/fullheight_dark_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/fullheight_light_linux.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/fullheight_dark_macos.png | https://raw.githubusercontent.com/ubuntu-flutter-community/musicpod/HEAD/.github/images/fullheight_light_macos.png |
The app icon has been made by Stuart Jaggers, thank you very much Stuart!
Thanks TheShadowOfHassen for packaging MusicPod as a Flatpak!
Thanks to all the MPV contributors!
Thank you @amugofjava for creating the very easy to use and reliable podcast_search!
Thanks @alexmercerind for the super performant Mediakit library and mpris_service dart implementation!
Thank you @KRTirtho for the very easy to use smtc_windows package and Flutter Discord RPC
Thank you @tomassasovsky for the dart implementation of radiobrowser-api!
Thank you @ClementBeal for the super fast, pure dart Audio Metadata Reader!
Thank you @escamoteur for creating get_it, watch_it, command_it and listen_it, which made my application faster and the source code cleaner!
Contributions are highly welcome. Especially translations.
The help of translators is highly appreciated! For translations MusiPod is now on Weblate thanks to @keunes:
https://hosted.weblate.org/projects/musicpod/app
Translation statusIf you find any error please feel free to report it as an issue and describe it as good as you can. If you want to contribute code, please create an issue first, then proceed as follows:
Please fork MusicPod to your GitHub namespace, clone it to your computer, create a branch named by yourself, commit your changes to your local branch, push them to your fork and then make a pull request from your fork to this repository. I recommend the vscode extension GitHub Pull Requests especially for people new to Git and GitHub.
sudo apt install libglib2.0-dev libgtk-3-dev curl git unzip xz-utils zip libglu1-mesa libmpv-dev mpv libnotify-devThe dependencies and test mocks are generated with build_runner. You need to run the build_runner command in order to re-generate dependencies, in case you changed the signatures of service methods, like this:
dart pub run build_runner build --force-jit
or if you use fvm:
fvm dart pub run build_runner build --force-jit
Now you can run the app with flutter run or fvm flutter run in the project directory. If not, please open an issue if I maybe have forgotten a step which I had locally, but not in the README.md.
The release please bot automatically creates a pull request when new changes after the last release are made with conventional commits. It force pushes those to its branch and updates the version string in pubspec.yaml and the changelog file. When the release please pull request is merged the version and changelog will be updated in main.
The linux snap packages are always build when a new commit lands in main. When a new release is made go to https://snapcraft.io/musicpod/releases and promote the latest snap from edge to stable.
fvm flutter build macos --releasecreate-dmg --idenfity=XXXXXXXX musicpod.app (XXXXXXXX is your apple dev ID which needs to be with your certificate in your mac...)Currently inno setup is needed. This hopefully changes some day when https://github.com/ubuntu-flutter-community/musicpod/issues/964 is merged.
msvcp140.dll
msvcp140_1.dll
msvcp140_2.dll
vcruntime140.dll
vcruntime140_1.dll
Test mocks are generated with Mockito. You need to run the build_runner command in order to re-generate mocks, in case you changed the signatures of service methods.
dart run build_runner build
MusicPod is basically a fancy front-end for MPV! Without it it would still look nice, but it wouldn't play any media :D!
The ever living discussion about state (Initially I didn't really like the word "state", in german it is "Zustand") in flutter is certainly an amusing topic. Often the word "state" means simply "data", "loading" and "error" state. Flutter let's the developer choose how to manage state, which can be awkward coming from UI frameworks with inbuilt data binding and state management solutions.
Amusing or not, it is incredibly important to understand where you keep state alive and when you want to dispose it and to treat the memory of the compuers of your users with respect!
So the "state management" topic is at least three fold:
Flutter provides very good out of the box solutions with State, StatefulWidgets and InheritedWidgets. Also for async state we have FutureBuilder and StreamBuilder.
But managing state becomes harder if your data is not only async but also needs to be shared across multiple widgets and you want to update and listen to it from different places in the app. And in case of MusicPod that data consists of local music, podcasts and radio stations, which all have different sources (and in case of slocal audio files, I initially underestimated how big the library of some users are...) which means you deal with huge lists of objects, which means huge amount of data, which means huge amount of allocated memory.
So if you want to access state from different places in your app, one could just make it available everywhere inside the app. But this means that the instantiated objects living in the heap of your apps process never will be garbage collected, which is really bad for every app.
So I was looking for a solution that:
Stateful widgets work fine and exactly as they should and dispose the data instantiated within them when the widgets are disposed but as soon as the state consists of multiple objects or fields it becomes hard to only redraw the parts that should be redrawn. And also when the the state needs to be created and updated asynchronoulsy it becomes a pain to only update loading error and loading states for this particular piece of state that you are currently interested in. Long story short: at a certain feature amount and size of your app, stateful widgets become a pain to manage and you need to look for a more scalable solution.
So I found my personal favorite solution with get_it plus watch_it plus command_it and listen_it. Additionally, to make my life easier when connecting the dependencies of classes I use Injectable for code generation of the dependency graph of get_it, by annotating the constructors of my classes and then running the build_runner command to generate the code for get_it.
(get_it, watch_it, listen_it and command_it be obtained with flutter_it which is a meta package for all of them.)
Family registry with auto-disposal: screen- and item-scoped managers are automatically disposed and garbage collected when their commands have no active listeners! (Much to my regret, flutter_it does not provide such a family / auto-dispose feature out of the box, so I had to implement my own.)WIP
Reading the local covers and fetching remote covers for radio data happens inside additional second dart isolates. When idle MusiPod's CPU power consumption is 0%. For a 10 years old intel dual core, the CPU usage is about 2% while playing music, since only the parts are redrawn which need to be, thanks to watch_it. Memory allocation can temporarily spike when loading large datasets on a page, but page-scoped managers and their data are automatically dereferenced and scheduled for disposal 5 seconds after navigation when listener counts drop to zero, keeping the active heap lean without retaining dormant screen state (the same behaviour can ofc be achieved with flutter's stateful widgets, but I prefer this architecture for the reasons mentioned above in the "state" section).
Preferences are stored with shared_preferences, the rest is stored within drift in a local sqlite database.