summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--player/player.go58
1 files changed, 49 insertions, 9 deletions
diff --git a/player/player.go b/player/player.go
index cb613d4..8e6db21 100644
--- a/player/player.go
+++ b/player/player.go
@@ -73,6 +73,15 @@ type stopRequest struct {
response chan<- stopResult
}
+type seekResult struct {
+ err error
+}
+
+type seekRequest struct {
+ pos float64
+ response chan<- seekResult
+}
+
type addUpdateHandlerResult struct {
err error
}
@@ -116,11 +125,12 @@ type Player struct {
stdlog *log.Logger
dbglog *log.Logger
state State
- len time.Duration
+ duration time.Duration
loadChan chan loadRequest
playChan chan playRequest
pauseChan chan pauseRequest
stopChan chan stopRequest
+ seekChan chan seekRequest
updateChan chan updateData
addUpdateHandlerChan chan addUpdateHandlerRequest
updateCBs []*pUpdateCB
@@ -131,23 +141,23 @@ func (p *Player) onMessage(bus *gst.Bus, msg *gst.Message) {
case gst.MESSAGE_EOS:
p.pipe.SetState(gst.STATE_NULL)
p.state = IDLE
- p.len = 0
- p.updateChan <- updateData{len: p.len}
+ p.duration = 0
+ p.updateChan <- updateData{len: p.duration}
case gst.MESSAGE_WARNING:
warn, _ := msg.ParseWarning()
p.stdlog.Printf("GStreamer Pipeline Warning: %s", warn)
case gst.MESSAGE_ERROR:
p.pipe.SetState(gst.STATE_NULL)
p.state = IDLE
- p.len = 0
- p.updateChan <- updateData{len: p.len}
+ p.duration = 0
+ p.updateChan <- updateData{len: p.duration}
err, _ := msg.ParseError()
p.stdlog.Printf("GStreamer Pipeline Error: %s", err)
case gst.MESSAGE_ASYNC_DONE:
len, ok := p.pipe.QueryDuration(gst.FORMAT_TIME)
if ok {
- p.len = time.Duration(len)
- p.updateChan <- updateData{len: p.len}
+ p.duration = time.Duration(len)
+ p.updateChan <- updateData{len: p.duration}
} else {
p.stdlog.Printf("GStreamer Pipeline Error: unable to query duration of file")
}
@@ -161,7 +171,7 @@ func (p *Player) onMessage(bus *gst.Bus, msg *gst.Message) {
meter[i] = MeterChannel{Peak: peak[i].(float64), Decay: decay[i].(float64)}
}
pos := time.Duration(s.Data["stream-time"].(uint64))
- p.updateChan <- updateData{len: p.len, pos: pos, meter: meter}
+ p.updateChan <- updateData{len: p.duration, pos: pos, meter: meter}
case gst.MESSAGE_STATE_CHANGED:
default:
p.dbglog.Printf("GStreamer Message: unknown type '%s'", msg.GetTypeName())
@@ -232,6 +242,17 @@ func (p *Player) stop() (resp stopResult) {
return
}
+func (p *Player) seek(pos float64) (resp seekResult) {
+ postime := int64(float64(p.duration) * pos)
+ switch p.state {
+ case PLAYING:
+ fallthrough
+ case PAUSED:
+ p.pipe.SeekSimple(gst.FORMAT_TIME, gst.SEEK_FLAG_FLUSH|gst.SEEK_FLAG_KEY_UNIT, postime)
+ }
+ return
+}
+
func (p *Player) addUpdateHandler(callback UpdateCB, userdata interface{}) (resp addUpdateHandlerResult) {
p.updateCBs = append(p.updateCBs, &pUpdateCB{callback, userdata})
return
@@ -262,6 +283,8 @@ func (p *Player) dispatchRequests() {
req.response <- p.pause()
case req := <-p.stopChan:
req.response <- p.stop()
+ case req := <-p.seekChan:
+ req.response <- p.seek(req.pos)
case req := <-p.addUpdateHandlerChan:
req.response <- p.addUpdateHandler(req.callback, req.userdata)
case u := <-p.updateChan:
@@ -330,6 +353,7 @@ type PlayerChan struct {
play chan<- playRequest
pause chan<- pauseRequest
stop chan<- stopRequest
+ seek chan<- seekRequest
addUpdateHandler chan addUpdateHandlerRequest
}
@@ -387,6 +411,20 @@ func (p *PlayerChan) Stop() error {
return nil
}
+func (p *PlayerChan) Seek(pos float64) error {
+ resCh := make(chan seekResult)
+ req := seekRequest{}
+ req.pos = pos
+ req.response = resCh
+ p.seek <- req
+
+ res := <-resCh
+ if res.err != nil {
+ return res.err
+ }
+ return nil
+}
+
func (p *PlayerChan) AddUpdateHandler(callback UpdateCB, userdata interface{}) error {
resCh := make(chan addUpdateHandlerResult)
req := addUpdateHandlerRequest{}
@@ -408,6 +446,7 @@ func (p *Player) GetInterface() *PlayerChan {
ch.play = p.playChan
ch.pause = p.pauseChan
ch.stop = p.stopChan
+ ch.seek = p.seekChan
ch.addUpdateHandler = p.addUpdateHandlerChan
return ch
}
@@ -415,7 +454,7 @@ func (p *Player) GetInterface() *PlayerChan {
func NewPlayer(basepath string, stdlog *log.Logger, dbglog *log.Logger) (p *Player, err error) {
p = &Player{}
p.basepath = path.Clean(basepath)
- p.len = 0
+ p.duration = 0
if stdlog != nil {
p.stdlog = stdlog
} else {
@@ -430,6 +469,7 @@ func NewPlayer(basepath string, stdlog *log.Logger, dbglog *log.Logger) (p *Play
p.playChan = make(chan playRequest)
p.pauseChan = make(chan pauseRequest)
p.stopChan = make(chan stopRequest)
+ p.seekChan = make(chan seekRequest)
p.updateChan = make(chan updateData, 20)
p.addUpdateHandlerChan = make(chan addUpdateHandlerRequest)