Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 自动缓存音乐 #139

Merged
merged 9 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ require (
github.com/gookit/gcli/v2 v2.3.4
github.com/gookit/ini/v2 v2.2.2
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/markthree/go-get-folder-size v0.3.4
github.com/mattn/go-runewidth v0.0.14
github.com/muesli/termenv v0.15.1
github.com/pkg/errors v0.9.1
Expand Down Expand Up @@ -59,6 +60,7 @@ require (
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/panjf2000/ants/v2 v2.8.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/crypto v0.10.0 // indirect
Expand Down
9 changes: 7 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/markthree/go-get-folder-size v0.3.4 h1:uflPpLVzg0G1y+WgcushNkVfsB2JoKlDUjNDxsjf9v4=
github.com/markthree/go-get-folder-size v0.3.4/go.mod h1:wfUR1y12nyc0lR9bOZEu7ZcK/uEmb+W5eU55ABhUdKY=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
Expand Down Expand Up @@ -145,6 +146,8 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs=
github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ=
github.com/panjf2000/ants/v2 v2.8.0 h1:4p4gPabD6iNM9Y5NpMc0g0L15uXDmfn6jkW5KP+oiHQ=
github.com/panjf2000/ants/v2 v2.8.0/go.mod h1:KIBmYG9QQX5U2qzFP/yQJaq/nSb6rahS9iEHkrCMgM8=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand All @@ -163,12 +166,14 @@ github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EE
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/telanflow/cookiejar v0.0.0-20190719062046-114449e86aa5 h1:gTQl5nPlc9B53vFOKM8aJHwxB2BW2kM49PVR5526GBg=
github.com/telanflow/cookiejar v0.0.0-20190719062046-114449e86aa5/go.mod h1:qNgA5MKwTh103SxGTooqZMiKxZTaV9UV3KjN7I7Drig=
github.com/urfave/cli v1.22.9/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
Expand Down
6 changes: 5 additions & 1 deletion hack/version.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,9 @@ fi
echo AppVersion "${VERSION}"
echo GitRevision "${GIT_REVISION}"
echo User "$(whoami)"
echo Host "$(hostname -f)"
if [[ ! `hostname -f` ]]; then
echo Host "$(cat /etc/hostname)"
else
echo Host "$(hostname -f)"
fi
echo Time "$(date '+%Y-%m-%dT%T')"``
6 changes: 6 additions & 0 deletions pkg/configs/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ type Registry struct {
MainDoubleColumn bool // 是否双列显示
MainDownloadDir string // 指定下载目录
MainShowAllSongsOfPlaylist bool // 显示歌单下所有歌曲
MainCacheDir string // 指定缓存目录
MainCacheLimit int64 // 缓存大小(以MB为单位),0为不使用缓存,-1为不限制,默认为0

UNMSwitch bool // UNM开关
UNMSources []string // UNM资源
Expand Down Expand Up @@ -86,6 +88,8 @@ func NewRegistryWithDefault() *Registry {
MainPProfPort: constants.MainPProfPort,
MainAltScreen: true,
MainEnableMouseEvent: true,
MainDownloadDir: "",
MainCacheLimit: 0,
PlayerEngine: constants.BeepPlayer,
PlayerBeepMp3Decoder: constants.BeepGoMp3Decoder,

Expand Down Expand Up @@ -153,6 +157,8 @@ func NewRegistryFromIniFile(filepath string) *Registry {
registry.MainDoubleColumn = ini.Bool("main.doubleColumn", true)
registry.MainDownloadDir = ini.String("main.downloadDir", "")
registry.MainShowAllSongsOfPlaylist = ini.Bool("main.showAllSongsOfPlaylist", false)
registry.MainCacheDir = ini.String("main.cacheDir", "")
registry.MainCacheLimit = ini.Int64("main.cacheLimit", 0)

defaultPlayer := constants.BeepPlayer
if runtime.GOOS == "darwin" {
Expand Down
13 changes: 11 additions & 2 deletions pkg/player/beep_player.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http"
"os"
"path"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -72,6 +73,7 @@ func (p *beepPlayer) listen() {
var (
done = make(chan struct{})
resp *http.Response
reader io.ReadCloser
err error
ctx context.Context
cancel context.CancelFunc
Expand Down Expand Up @@ -116,9 +118,16 @@ func (p *beepPlayer) listen() {
panic(err)
}

if resp, err = p.httpClient.Get(p.curMusic.Url); err != nil {
if !strings.HasPrefix(p.curMusic.Url, "http") {
reader, err = os.Open(p.curMusic.Url)
if err != nil {
panic(err)
}
} else if resp, err = p.httpClient.Get(p.curMusic.Url); err != nil {
p.stopNoLock()
continue
} else {
reader = resp.Body
}

go func(ctx context.Context, cacheWFile *os.File, read io.ReadCloser) {
Expand Down Expand Up @@ -156,7 +165,7 @@ func (p *beepPlayer) listen() {
_ = p.curStreamer.Seek(pos)
p.ctrl.Streamer = beep.Seq(beep.StreamerFunc(p.streamer), beep.Callback(doneHandle))
}
}(ctx, p.cacheWriter, resp.Body)
}(ctx, p.cacheWriter, reader)

var N = 512
if p.curMusic.Type == Flac {
Expand Down
50 changes: 42 additions & 8 deletions pkg/player/mpd_player.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package player
import (
"fmt"
"os/exec"
"path"
"strconv"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -192,7 +194,36 @@ func (p *mpdPlayer) listen() {
}
}

p.curSongId, err = p.client().AddID(p.curMusic.Url, 0)
var (
url string
isCache bool
)
if strings.HasPrefix(p.curMusic.Url, "http") {
url = p.curMusic.Url
isCache = false
} else {
url = path.Base(p.curMusic.Url)
isCache = true
}

if isCache {
_, err := p.client().Rescan(url)
mpdErrorHandler(err, false)
for {
var attr map[string]string
if attr, err = p.client().Status(); err != nil {
mpdErrorHandler(err, true)
break
}
if _, ok := attr["updating_db"]; ok {
continue
}
// 确保更新完成
break
}
}

p.curSongId, err = p.client().AddID(url, 0)
mpdErrorHandler(err, false)

// 计时器
Expand All @@ -212,13 +243,16 @@ func (p *mpdPlayer) listen() {

err = p.client().PlayID(p.curSongId)
mpdErrorHandler(err, false)
// Doing this because github.com/fhs/gompd/v2/mpd hasn't implement "addtagid" yet
err = p.client().Command("addtagid %d %s %s", p.curSongId, "artist", p.curMusic.ArtistName()).OK()
mpdErrorHandler(err, false)
err = p.client().Command("addtagid %d %s %s", p.curSongId, "album", p.curMusic.Album.Name).OK()
mpdErrorHandler(err, false)
err = p.client().Command("addtagid %d %s %s", p.curSongId, "title", p.curMusic.Name).OK()
mpdErrorHandler(err, false)
if !isCache {
imxyy1soope1 marked this conversation as resolved.
Show resolved Hide resolved
// Doing this because github.com/fhs/gompd/v2/mpd hasn't implement "addtagid" yet
command := "addtagid %d %s %s"
err = p.client().Command(command, p.curSongId, "artist", p.curMusic.ArtistName()).OK()
mpdErrorHandler(err, true)
err = p.client().Command(command, p.curSongId, "album", p.curMusic.Album.Name).OK()
mpdErrorHandler(err, true)
err = p.client().Command(command, p.curSongId, "title", p.curMusic.Name).OK()
mpdErrorHandler(err, true)
}
p.Resume()
}
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/ui/main_ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,9 @@ func (main *MainUIModel) keyMsgHandle(msg tea.KeyMsg, m *NeteaseModel) (tea.Mode
case "E":
// 追加到播放列表末尾
addSongToPlaylist(m, false)
case "u", "U":
// 清除歌曲缓存
clearSongCache(m)
case "r", "R":
// rerender
return m, m.rerenderTicker(true)
Expand Down
1 change: 1 addition & 0 deletions pkg/ui/menu_help.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func NewHelpMenu() *HelpMenu {
{Title: "x/X", Subtitle: "快退1s/5s"},
{Title: ";/:", Subtitle: "收藏选中歌单"},
{Title: "'/\"", Subtitle: "取消收藏选中歌单"},
{Title: "u/U", Subtitle: "清除音乐缓存"},
}

return menu
Expand Down
24 changes: 22 additions & 2 deletions pkg/ui/operate.go
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ func downloadSelectedSong(m *NeteaseModel) {
return
}
songs := menu.Songs()
utils.DownloadMusic(songs[selectedIndex])
go utils.DownloadMusic(songs[selectedIndex])
}

func downloadPlayingSong(m *NeteaseModel) {
Expand All @@ -662,7 +662,7 @@ func downloadPlayingSong(m *NeteaseModel) {
return
}

utils.DownloadMusic(m.player.playlist[m.player.curSongIndex])
go utils.DownloadMusic(m.player.playlist[m.player.curSongIndex])
}

func albumOfPlayingSong(m *NeteaseModel) {
Expand Down Expand Up @@ -1055,3 +1055,23 @@ func delSongFromPlaylist(m *NeteaseModel) {

m.refreshMenuList()
}

func clearSongCache(m *NeteaseModel) {
loading := NewLoading(m)
loading.start()
defer loading.complete()
err := utils.ClearMusicCache()
if err != nil {
utils.Notify(utils.NotifyContent{
Title: "清除缓存失败",
Text: err.Error(),
GroupId: constants.GroupID,
})
} else {
utils.Notify(utils.NotifyContent{
Title: "清除缓存成功",
Text: "缓存已清除",
GroupId: constants.GroupID,
})
}
}
2 changes: 1 addition & 1 deletion pkg/ui/player.go
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ func (p *Player) PlaySong(song structs.Song, direction PlayDirection) error {

p.LocatePlayingSong()
p.Player.Paused()
url, musicType, err := utils.GetSongUrl(song.Id)
url, musicType, err := utils.GetSongUrl(song)
if url == "" || err != nil {
p.progressRamp = []string{}
p.playErrCount++
Expand Down
5 changes: 5 additions & 0 deletions utils/embed/go-musicfox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ enableMouseEvent=true
doubleColumn=true
# 下载目录,默认为${MUSICFOX_ROOT}/download
downloadDir=
# 缓存目录,默认为${MUSICFOX_ROOT}/cache
# !!!注意!!! 如果使用mpd,mpd配置中的"music_directory"必须与cacheDir一致
cacheDir=
# 缓存大小(以MB为单位),0为不使用缓存,-1为不限制,默认为0
cacheLimit=0
# 是否显示歌单下所有歌曲,默认不开启,仅获取歌单前1000首,开启后可能会占用更多内存(大量歌曲数据)和带宽(会同时发送多个请求获取歌单下歌曲数据)
showAllSongsOfPlaylist=false

Expand Down
Loading