天天看點

【.NET 與樹莓派】MPD 的 Mini-API 封裝

在前面的水文中,一方面,老周向各位同學介紹了通過 TCP 連接配接來通路 MPD 服務;另一方面,也簡單示範了 ASP.NET Core 的“極簡 API”(Mini API)。本篇老周就簡單說一下如何用 Mini API 來封裝對 MPD 伺服器的通路。内容僅供參考,也許你會想到更好的方案。

你可能會問:老周,你這個懶B,上次寫完之後,咋等了這麼久才寫這一篇?實不相瞞,因為遇到問題了……這問題主要出在了“add”指令上。

這個指令的功能是把某一曲目添加到目前播放清單中(不管你是否加載以前儲存的清單,總之就是目前正在用的播放清單),其格式為:

還記得前面的内容乎?咱們在配置 MPD 時,會指定一個專門放置音樂檔案的目錄,是以,這個音頻URL一般使用相對路徑,即相對音樂目錄的相對路徑。

比如,你配置的音樂目錄是 /home/pi/mpd/music,然後,你在 music 目錄下放了一個子目錄叫“裝逼2021全新專輯”,裡面有三個檔案,結構大緻如下:

即,“千年裝逼魂.wav”的全路徑是 /home/pi/mpd/music/裝逼2021全新專輯/千年裝逼魂.wav,但是,使用 add 指令時,隻使用相對路徑即可,相對于音樂目錄。

URL最好加上雙引号,因為路徑中帶有空格的機率很高。

那麼,老周遇到的問題是啥?因為這個 add 指令會引用音頻檔案路徑,這文本中避免不了會出現漢字字元。說到這裡你估計明白了,對的,讓人頭痛的老問題——文本編碼問題。有漢字字元就不能使用 ASCII 編碼了,但顯式使用 UTF-8 編碼也不行,經多次嘗試,還是報錯。

終于,被老周測出一個完美解決方法——直接使用 Encoding.Default,讓運作時自動使用與系統一緻的編碼。真 TM 沒想到,這一招居然把所有問題全解決了,不再報錯了。果然,預設的是最使的。

----------------------------------------------------------------------------------------------------

既然問題解決了,那麼這篇水文就能寫了。

為了友善操作,咱們不妨先單獨封裝一個類,這個類專用來與 MPD 服務程序通信。現在我把整個類的代碼先放出來,然後老周再說一下核心部分。

我這個類并沒有實作所有的指令,隻包裝了常用的指令,你隻要明白其原理後,你自己也可以擴充。

對了,這裡得糾正一點:老周在前面的文章中示範TCP協定通路 MPD,是直接發送文本的。由于前面我示範的隻有 listall 一個指令,是以在連接配接 MPD 伺服器後就馬上發送 listall 指令,然後就接收伺服器回應。上次老周說的是:伺服器先回複了一句 OK + MPD 版本号,再發檔案清單,最後一句 OK。

其實這裡老周弄錯了,MPD 伺服器回複的第一句 OK + MPD版本号并不是響應 listall 指令的,而是當用戶端與它建立TCP連接配接成功後就馬上回複的,是以,MPD 對 listall 指令的回複的檔案清單 + OK。

是以,再回過頭來看剛剛那個類,在構造函數中,我讓 TcpClient 對象連接配接MPD服務(伺服器在本機)。

另一個核心方法是 SendCommand,它的功能是向 MPD 伺服器發送指令,然後傳回一個 TextReader 對象,這個 reader 可以讀取 MPD 伺服器的響應消息。

接着,各種控制方法都是調用這個方法與 MPD 伺服器難信,封裝後對外公開。

這個 MPDTCPClient 封裝類在執行個體化時建立連接配接,在釋放/清理時關閉連接配接。接着我們把這個類注冊為依賴注入服務,并且是短暫執行個體模式(每次注入時都執行個體化,用完就釋放),這可以避免 TCP 連接配接被長期占用導緻環境污染。

接下來,咱們就可以使用 MapXXX 擴充方法來定義 Mini API。

這個 API 的基本套路就是:若成功執行,傳回 200(OK);若執行失敗,傳回 500。

MapXXX 方法的第二個參數是一個【萬能】委托對象,注意在定義委托時,需要一個 MPDTCPClient 類型的參數,這個參數會自動擷取到依賴注入進來的對象引用。

大體就是這樣,你可以根據需要,自行補充其他 MPD 指令的封裝。

有了這個 API 的封裝,實作 MPD 用戶端就靈活多了,你可以做移動App,也可以做成 Web App,也可以做成桌面程式。反正你愛咋整就咋整,不管用啥做用戶端程式,隻要調用這些 Web API 即可。

最後,拿幾個 API 測試一下。

先測一下列出所有指令的 API。

 傳回的結果如下:

再測一下 listall 指令。

向目前播放清單中添加一首曲子,注意:MPD 服務傳回的檔案名是有“file: ”開頭的,而咱們傳遞給 add 指令時,不需要"file:",直接用相對路徑即可(建議加上雙引号)。

再測試一下 playlist 接口,列出目前播放清單中的曲目。

 傳回的播放清單如下:

“file:”前面的數字是曲目在播放清單中的位置,從 0 開始計算,這樣一來,在使用 play 指令時就可以通過這個數字來指定要播放的曲目,比如要播放第二首(位置1)。

不過,剛才老周寫的 play API是沒有參數的,預設播放整個清單,咱們可以改一下。

如果 pos 參數為 -1,表示從頭播放整個清單。

現在,可以調用了,播放第二首曲子。 

好了,今天的文章就水到這裡了。預告一下,下一篇水文中,咱們玩玩 LED 彩色燈帶。