我正在使用libvlc
(go binding) 在 TUI 中播放音乐。我没有使用media_list_player
具有Next
和Previous
方法的 , 而是遵循此答案https://stackoverflow.com/a/44647523/4443226的建议来使用常规media_player
和循环:
import vlc
import time
my_list = ['vp1.mp3','happy.mp3']
instance = vlc.Instance()
player = instance.media_player_new()
playing = set([1,2,3,4])
for i in my_list:
player.set_mrl(i)
player.play()
play=True
while play == True:
time.sleep(1)
play_state = player.get_state()
if play_state in playing:
continue
else:
play = False
这样做的好处是我可以获得当前歌曲的索引,并且可以获得当前播放歌曲的位置和持续时间。
我在 Go 中实现了它,问题之一是我无法(有效地)实现Next
和Previous
唱歌。
部分问题是这个播放循环必须与 UI 线程分开。goroutine
我chan
用来发送停止goroutine
和跳过歌曲的信号。
func playAlbum(p *vlc.Player, a Album, l *tui.List, s *tui.StatusBar, done, next, prev chan struct{}) (err error) {
playlist := make([]*vlc.Media, 0)
for _, path := range a.Paths {
media, err := vlc.NewMediaFromPath(path)
// check eturn err
playlist = append(playlist, media)
}
for idx := range playlist {
p.SetMedia(playlist[idx])
err = p.Play()
// check return err
status, err := p.MediaState()
// check return err
PlaybackLoop:
for status != vlc.MediaEnded {
status, err = p.MediaState()
// continue with err
l.SetSelected(idx) // TUI list of songs
song := songStatus(a, l.Selected())
s.SetPermanentText(song) // TUI status bar
select {
case <-next:
break PlaybackLoop
case <-prev:
continue // TODO: implement previous
case <-done:
return err
default:
time.Sleep(50 * time.Millisecond)
}
}
}
return err
}
我无法实现Previous
,因为我不能只返回 for 循环。
理想情况下,我想我想使用libvlc
media_list_player
. 但是,如果我无法获得歌曲时长和长度以及歌曲在 中的索引media_list
,我宁愿使用这种方法。
如果我必须media_player
改用,有没有比使用嵌套循环和通道更好的方法来处理播放?可以使用以前的东西吗?