MusicPod 是一款適用於 Linux 桌面、MacOS 和 Windows 的本機音樂、廣播、電視和播客播放器。 (Android 已計劃,但尚未確定何時推出。)
作業系統 | 如何安裝 |
---|---|
Linux | 或者 |
視窗 | 發布頁面 |
蘋果系統 | 發布頁面 |
安卓 | 在製品 |
特徵 | 黑暗Linux | 輕型Linux | 黑暗的MacOS | 輕量MacOS |
---|---|---|---|---|
播放本地音訊 | ||||
尋找按元資料排序的本地音頻 | ||||
播放廣播電台,尋找冰標籤和藝術品! | ||||
播放和下載播客、安全進度、排序劇集等等! | ||||
視訊播客支援! | ||||
發現播客,根據您的喜好進行過濾 | ||||
發現廣播電台,根據您的喜好進行篩選 | ||||
不同的視圖模式 |
該應用程式圖標是由 Stuart Jaggers 製作的,非常感謝 Stuart!
感謝 TheShadowOfHassen 將 MusicPod 打包為 Flatpak!
感謝所有 MPV 貢獻者!
感謝 @amugofjava 創建了非常易於使用且可靠的 podcast_search!
感謝 @alexmercerind 提供的超高效能 Mediakit 函式庫和 mpris_service dart 實作!
感謝 @KRTirtho 提供了非常容易使用的 smtc_windows 套件和 Flutter Discord RPC
感謝@tomassasovsky 的 radiobrowser-api 的 dart 實現!
感謝 @ClementBeal 提供的超快、純 dart 音頻元數據閱讀器!
感謝 @escamoteur 創建 get_it 和 watch_it,這使我的應用程式更快,原始程式碼更乾淨!
非常歡迎您的貢獻。尤其是翻譯。請將MusicPod 分叉到您的GitHub 命名空間,將其克隆到您的計算機,創建您自己命名的分支,將更改提交到本地分支,將它們推送到您的分支,然後從您的分支向此存儲庫發出拉取請求。我推薦 vscode 擴充 GitHub Pull Requests,特別是對於 Git 和 GitHub 的新手。
要翻譯成您的語言,請更改相應的app_xx.arb
文件,其中xx
是您的語言的小寫語言代碼。如果該檔案尚不存在,請建立它並將 app_en.arb 的whole
內容複製到其中,然後僅更改您翻譯的值,但保持鍵不變。強烈建議使用 Google 的 vscode 擴充 arb 編輯器以避免 arb 語法錯誤。也推薦谷歌翻譯擴充。
如果您發現任何錯誤,請隨時將其報告為問題並儘可能詳細地描述它。如果您想貢獻程式碼,請先建立問題。
測試模擬是用 Mockito 產生的。如果您變更了服務方法的簽名,您需要執行build_runner
指令才能重新產生模擬。
dart run build_runner build
MusicPod 基本上就是 MPV 的一個奇特前端!如果沒有它,它看起來仍然不錯,但它不會播放任何媒體:D!
MusicPod 使用 MVVM 架構模式,最適合這種反應式應用程式的需求,並將所有層分開,以便我們可以在需要時交換某一層的實作。 MVVM也是Flutter自己推薦的。
應用程式、播放器、搜尋和每個主頁都有自己的一組小部件、一個或多個視圖模型,它們依賴於一個或多個服務。
所有服務和 ViewModel 都是透過 get_it 延遲註冊的,這意味著它們只有在第一次透過di
或di
定位時才會被實例化。
流程圖LR
classDef 視圖填滿:#0e84207d
classDef 視圖模型填充:#e9542080
classDef模型填充:#77216f80
查看["`
**看法**
(小工具)
`"]:::view--watchProperty-->ViewModel["`
**視圖模型**
(變更通知程序)
`"]:::viewmodel--監聽/取得屬性-->模型["`
**(域)模型**
(服務)
`"]:::模型
ViewModel--通知-->視圖
模型--changedProperties.add(true)-->ViewModel
ViewModel 依賴透過其建構函式給出的服務,它們透過服務定位器 get_it 定位。這使得它們易於測試,因為您可以用模擬服務替換服務。
ViewModel 是 ChangeNotifier。他們可以使用notifyListener
方法來讓偵聽器(具體:UI 類別)做出反應(即重建)。
ViewModel 持有它們所依賴的服務的 StreamSubscription。如果屬性只是非持久性 UI 狀態,則它們會保存在 ViewModel 中。如果它們不只如此,那麼它們只是服務屬性的取得者。因此,如果服務的屬性發生更改,ViewModel 將透過propertiesChanged 串流收到通知,如果我們希望 UI 注意到,在listen
回呼中我們將通知 UI(偵聽器)。
關於實現此架構的包,我從提供者到 Riverpod 經歷了相當長的旅程。
我發現我個人最喜歡的解決方案是 get_it 加上它的 watch_it 擴展,因為這最適合這個應用程式和 MVVM 架構的需求,而且不會過度侵入 flutter widget 樹的 API。
這樣,所有層都清晰分離,易於重新實現且易於遵循,即使這會帶來一點樣板程式碼。
如果 ViewModel 的屬性發生變更後希望重新建構 Widget,我們可以使用 watch_it 套件的watchPropertyValue
方法:
final audio = watchPropertyValue (( PlayerModel m) => m.audio);
這使得它變得更容易,即使我們也可以只使用 ListenableBuilder 中內建的 flutters。
本機封面和遠端封面在載入/取得後都會快取在CoverStore
和UrlStore
中。
讀取本地覆蓋物和獲取遠端覆蓋物的無線電資料發生在額外的第二個省份隔離內。
首選項透過shared_preferences 儲存。