Commit a703cfd9 authored by Jonny Schäfer's avatar Jonny Schäfer
Browse files

pages contain a fixed number of videos and display the video id in

the playback status

Also add new lists module which implements concurrent page update
and caching of previously loaded pages.
parent 679fb327
Pipeline #282 skipped
package main
import (
"sync"
)
// lazy filled list
type listLazy struct {
update func(int) []*videoContainer
dry bool
state int
content []*videoContainer
}
// temporary storage for parallel data acquisition
type listChunk struct {
data *[]*videoContainer
avail *sync.Mutex
}
// listUpdateChunk concurrently runs the lists update function and
// returns a listChunk. The listChunk.avail mutex will be unlocked when
// finished.
func (l *listLazy) listUpdateChunk(state int) *listChunk {
cnk := &listChunk{&[]*videoContainer{}, &sync.Mutex{}}
cnk.avail.Lock()
go func() {
*cnk.data = l.update(state)
cnk.avail.Unlock()
}()
return cnk
}
// listNew creates a new lazy list with the given update function.
func listNew(update func(int) []*videoContainer) *listLazy {
return &listLazy{update, false, 0, []*videoContainer{}}
}
// listGet returns the element with the given index from the list. If
// the list is too short the lists update function will be called until
// the requested element is available. If the element could not be acquired
// nil is returned.
func (l *listLazy) listGet(index int) *videoContainer {
par := 5 // parallel update count
for index >= len(l.content) && !l.dry {
recv := 0
temp := make([]*listChunk, par)
for i, _ := range temp {
temp[i] = l.listUpdateChunk(l.state + i)
}
for _, c := range temp {
c.avail.Lock()
c.avail.Unlock()
if len(*c.data) == 0 {
l.dry = true
}
l.content = append(l.content, *c.data...)
recv += len(*c.data)
l.state++
}
}
if index < len(l.content) {
return l.content[index]
}
return nil
}
// listLazy tries to return the requested slice from the list. If the
// list is too short the lists update function will be called until
// the length is sufficient. If the list is too small, a smaller slice
// then requested may be returned.
func (l *listLazy) listSlice(begin, end int) []*videoContainer {
if l.listGet(end) == nil {
if l.listGet(begin) == nil {
return l.content[0:0]
}
return l.content[begin:]
}
return l.content[begin:end]
}
......@@ -45,11 +45,13 @@ const (
)
var (
logicVarWindow = logicWindowNone
logicVarVideos []*videoContainer = []*videoContainer{}
logicVarUsers = []string{}
logicVarUser = ""
logicVarSearch = ""
logicVarLineCount = 30
logicVarWindow = logicWindowNone
logicVarVideos []*videoContainer = []*videoContainer{}
logicVarLazy = &listLazy{}
logicVarUsers = []string{}
logicVarUser = ""
logicVarSearch = ""
)
// logicAction parses the input string and performs the given action
......@@ -91,7 +93,12 @@ func logicTrim(trim string) string {
// logicSearch searches for the given video title
func logicSearch(title string) {
logicSearchPage(title, "1")
upd := func(state int) []*videoContainer {
return videoListSearch(title, strconv.Itoa(state))
}
logicVarLazy = listNew(upd)
logicSearchPage(title, "0")
}
//logicSearchPage searches the title in the given page
......@@ -99,7 +106,12 @@ func logicSearchPage(title, page string) {
cliStatus("page " + page + " | searching for: " + title)
logicVarWindow = logicWindowSearch
logicVarSearch = title
list := videoListSearch(title, page)
pnum, err := strconv.Atoi(page)
errorCare(err)
list := logicVarLazy.listSlice(pnum*logicVarLineCount, (pnum+1)*logicVarLineCount)
if list == nil {
cliStatusError("network error: unable to load data")
return
......@@ -128,7 +140,7 @@ func logicNumber(command string) {
fallthrough
case logicWindowSearch:
if sel < len(logicVarVideos) {
logicPlay(player, logicVarVideos[sel]) // non blocking
logicPlay(splits[0], player, logicVarVideos[sel]) // non blocking
} else {
cliStatusError("error: video id not in list")
}
......@@ -370,13 +382,13 @@ func logicSetPlayer(player string) {
}
// logicPlay plays the video in the given player
func logicPlay(player string, video *videoContainer) {
func logicPlay(info, player string, video *videoContainer) {
cmd := append(strings.Split(player, " "), "https://www.youtube.com/watch?v="+video.url)
exe := exec.Command(cmd[0], cmd[1:]...)
if err := exe.Start(); err != nil {
cliStatusError(fmt.Sprint("playback error: ", err))
} else {
cliStatus("[" + player + "] " + video.title)
cliStatus("[" + info + "][" + player + "] " + video.title)
}
go exe.Wait()
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment