使用libvlc播放实现上一个功能。

huangapple go评论94阅读模式
英文:

Implement previous with libvlc playback

问题

我正在使用libvlc(go绑定)在TUI中播放音乐。我没有使用media_list_player,它有NextPrevious方法,而是按照这个答案的建议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中实现了这个方法,其中一个问题是,我无法有效地实现NextPrevious歌曲。

问题的一部分是,这个播放循环必须在与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)
        // 检查错误并返回
        playlist = append(playlist, media)
    }

    for idx := range playlist {
        p.SetMedia(playlist[idx])
        err = p.Play()
        // 检查错误并返回

        status, err := p.MediaState()
        // 检查错误并返回

    PlaybackLoop:
        for status != vlc.MediaEnded {
            status, err = p.MediaState()
            // 继续并检查错误

            l.SetSelected(idx) // TUI歌曲列表

            song := songStatus(a, l.Selected())
            s.SetPermanentText(song) // TUI状态栏

            select {
            case <-next:
                break PlaybackLoop
            case <-prev:
                continue // TODO: 实现上一首
            case <-done:
                return err
            default:
                time.Sleep(50 * time.Millisecond)
            }
        }
    }
    return err
}

我无法实现Previous,因为我不能在for循环中回退。

理想情况下,我认为我应该使用libvlcmedia_list_player。然而,如果我无法获取media_list中歌曲的持续时间长度索引,我宁愿使用这种方法。

如果我必须使用media_player,有没有比使用嵌套循环和通道更好的处理播放的方法?有没有办法实现上一首

英文:

I'm using libvlc (go binding) to play music in a TUI. Instead of using the media_list_player, which has Next and Previous methods, I followed the advice of this answer https://stackoverflow.com/a/44647523/4443226 to use the regular media_player and a loop:

<!-- language: python -->

import vlc
import time
my_list = [&#39;vp1.mp3&#39;,&#39;happy.mp3&#39;]
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

This has the benefit that I can get the index of the current song and I can get the position and duration of the current playing song.

I implemented it in Go, and one of the problems, is that I am unable to implement (effectively) Next and Previous song.

Part of the problem is that this playback loop must be in a separate goroutine than the UI thread. I use chan to send signals for stopping the goroutine and skipping the song.

<!-- language: go -->

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 &lt;-next:
				break PlaybackLoop
			case &lt;-prev:
				continue // TODO: implement previous
			case &lt;-done:
				return err
			default:
				time.Sleep(50 * time.Millisecond)
			}
		}
	}
	return err
}

I am unable to implement Previous, because I can't just go back in the for loop.

Ideally I think I would like to use the libvlc media_list_player. However, if I can't get the song duration and length as well as the index of the song in the media_list, I would rather do this method.

If I must use the media_player instead, is there a better way to handle playback than using nested loops and channels? Something that can use previous?

答案1

得分: 1

根据与提问者的评论和讨论,确定使用链表可能是在尝试以较少的努力控制前进和后退的最佳方法。由于使用了Go语言,并且使用的模块需要goroutine,因此链表在goroutine中的使用也必须是安全的。

英文:

Based on the comments and discussion with the OP It was determined that a linked list was probably the best route in trying to control how to go forward and backwards with a bit less effort. Since Go is being used and the modules that are being used require goroutines the linked list also would have to be safe to use within goroutines.

huangapple
  • 本文由 发表于 2017年7月15日 23:38:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/45119930.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定