diff options
-rw-r--r-- | player/player.go | 58 |
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) |