120 lines
2.7 KiB
Go
120 lines
2.7 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"sync"
|
|
"time"
|
|
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
)
|
|
|
|
const (
|
|
playerMaxTitleLength = 30
|
|
)
|
|
|
|
var (
|
|
regexpPosDur = regexp.MustCompile(`AV: (\d+):(\d+):(\d+) \/ (\d+):(\d+):(\d+)`)
|
|
)
|
|
|
|
type playerModel struct {
|
|
// entry *feedEntry
|
|
// isPlayingVideo bool
|
|
|
|
// // video information
|
|
// videoDuration time.Duration
|
|
// videoPosition time.Duration
|
|
|
|
// TODO: make this smarter
|
|
// finished entries to send messages about
|
|
currentlyPlaying *feedEntry
|
|
playQueue []feedEntry
|
|
|
|
mpv *MPVPLayer
|
|
|
|
sync.RWMutex
|
|
}
|
|
|
|
func (m *playerModel) Init() tea.Cmd {
|
|
m.mpv = NewMPVPlayer()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *playerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
switch msg := msg.(type) {
|
|
case MsgPlayEntry:
|
|
f := feedEntry(msg)
|
|
m.queue(f)
|
|
}
|
|
|
|
// send message because it is finished
|
|
// we have a currentlyPlaying entry, but it is no longer playing
|
|
// which means we finished watching it
|
|
var cmds []tea.Cmd
|
|
if m.currentlyPlaying != nil && m.mpv.IsPlaying() == false {
|
|
if videoPercentageWatched(m.mpv.VideoPosition(), m.mpv.VideoDuration()) > 90 {
|
|
t := m.currentlyPlaying.ID
|
|
cmds = append(cmds, func() tea.Msg { return MsgWatchedEntry(t) })
|
|
}
|
|
|
|
// unset currentlyPlaying
|
|
m.currentlyPlaying = nil
|
|
|
|
if err := m.playNext(); err != nil {
|
|
cmds = append(cmds, func() tea.Msg { return MsgError(err) })
|
|
}
|
|
}
|
|
|
|
return m, tea.Batch(cmds...)
|
|
}
|
|
|
|
func (m *playerModel) View() string {
|
|
// return "NO DONT ASK"
|
|
return fmt.Sprintf("IsPlaying: %v, Pos: %v, Dur: %v, Per: %v", m.mpv.IsPlaying(), m.mpv.VideoPosition(), m.mpv.VideoDuration(), videoPercentageWatched(m.mpv.VideoPosition(), m.mpv.VideoDuration()))
|
|
|
|
if m.mpv.IsPlaying() {
|
|
timePos := time.Time{}.Add(m.mpv.VideoPosition())
|
|
timeDur := time.Time{}.Add(m.mpv.VideoDuration())
|
|
|
|
// truncate name if needed
|
|
// name := m.entry.Name
|
|
name := m.currentlyPlaying.Name
|
|
if len(name) > playerMaxTitleLength {
|
|
name = name[0:playerMaxTitleLength] + "..."
|
|
}
|
|
|
|
return fmt.Sprintf("Playing: %s (%s/%s %.1f%%)",
|
|
name,
|
|
timePos.Format(time.TimeOnly),
|
|
timeDur.Format(time.TimeOnly),
|
|
videoPercentageWatched(m.mpv.VideoPosition(), m.mpv.VideoDuration()),
|
|
)
|
|
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// other functions
|
|
func (m *playerModel) queue(f feedEntry) error {
|
|
m.playQueue = append(m.playQueue, f)
|
|
|
|
if len(m.playQueue) == 1 && m.mpv.IsPlaying() == false {
|
|
m.currentlyPlaying = &m.playQueue[0]
|
|
m.playQueue = m.playQueue[1:]
|
|
return m.mpv.Play(VideoID("TODO-remove-this"), m.currentlyPlaying.Link)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *playerModel) playNext() error {
|
|
if len(m.playQueue) > 0 && m.mpv.IsPlaying() == false {
|
|
m.currentlyPlaying = &m.playQueue[0]
|
|
m.playQueue = m.playQueue[1:]
|
|
return m.mpv.Play(VideoID("TODO-remove-this"), m.currentlyPlaying.Link)
|
|
}
|
|
|
|
return nil
|
|
}
|