Changeset - 4a5b37acd1f0
[Not reviewed]
default
0 1 0
drewp@bigasterisk.com - 8 months ago 2024-05-23 18:25:58
drewp@bigasterisk.com
private attrs
1 file changed with 19 insertions and 19 deletions:
0 comments (0 inline, 0 general)
src/light9/ascoltami/player.py
Show inline comments
 
@@ -20,48 +20,48 @@ class Player:
 
        end of a stream (for example, can be used to advance the song).
 
        It is called with one argument which is the URI of the song that
 
        just finished."""
 
        self.autoStopOffset = autoStopOffset
 
        self.playbin = self.pipeline = Gst.ElementFactory.make('playbin', None)
 

	
 
        self.playStartTime = 0
 
        self.lastWatchTime = 0
 
        self.autoStopTime = 0
 
        self.lastSetSongUri = None
 
        self.onEOS = onEOS
 
        self._playStartTime = 0
 
        self._lastWatchTime = 0
 
        self._autoStopTime = 0
 
        self._lastSetSongUri = None
 
        self._onEOS = onEOS
 

	
 
        task.LoopingCall(self.watchTime).start(.050)
 

	
 
        #bus = self.pipeline.get_bus()
 
        # not working- see notes in pollForMessages
 
        #self.watchForMessages(bus)
 

	
 
    def watchTime(self):
 
        try:
 
            self.pollForMessages()
 

	
 
            t = self.currentTime()
 
            log.debug("watch %s < %s < %s", self.lastWatchTime,
 
                      self.autoStopTime, t)
 
            if self.lastWatchTime < self.autoStopTime < t:
 
            log.debug("watch %s < %s < %s", self._lastWatchTime,
 
                      self._autoStopTime, t)
 
            if self._lastWatchTime < self._autoStopTime < t:
 
                log.info("autostop")
 
                self.pause()
 

	
 
            self.lastWatchTime = t
 
            self._lastWatchTime = t
 
        except Exception:
 
            traceback.print_exc()
 

	
 
    def watchForMessages(self, bus):
 
        """this would be nicer than pollForMessages but it's not working for
 
        me. It's like add_signal_watch isn't running."""
 
        bus.add_signal_watch()
 

	
 
        def onEos(*args):
 
            print("onEos", args)
 
            if self.onEOS is not None:
 
                self.onEOS(self.getSong())
 
            if self._onEOS is not None:
 
                self._onEOS(self.getSong())
 

	
 
        bus.connect('message::eos', onEos)
 

	
 
        def onStreamStatus(bus, message):
 
            print("streamstatus", bus, message)
 
            (statusType, _elem) = message.parse_stream_status()
 
@@ -83,46 +83,46 @@ class Player:
 
            # output has an error, since that's otherwise kind of
 
            # mysterious to diagnose. I don't think this is exactly
 
            # working.
 
            if msg.type == mt.ERROR:
 
                log.error(repr(msg.parse_error()))
 
            if msg.type == mt.EOS:
 
                if self.onEOS is not None:
 
                    self.onEOS(self.getSong())
 
                if self._onEOS is not None:
 
                    self._onEOS(self.getSong())
 
            if msg.type == mt.STREAM_STATUS:
 
                (statusType, _elem) = msg.parse_stream_status()
 
                if statusType == Gst.StreamStatusType.ENTER:
 
                    self.setupAutostop()
 

	
 
    def seek(self, t):
 
        isSeekable = self.playbin.seek_simple(
 
            Gst.Format.TIME,
 
            Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE | Gst.SeekFlags.SKIP,
 
            t * Gst.SECOND)
 
        if not isSeekable:
 
            raise ValueError('seek_simple failed')
 
        self.playStartTime = time.time()
 
        self._playStartTime = time.time()
 

	
 
    def setSong(self, songLoc, play=True):
 
        """
 
        uri like file:///my/proj/light9/show/dance2010/music/07.wav
 
        """
 
        log.info("set song to %r" % songLoc)
 
        self.pipeline.set_state(Gst.State.READY)
 
        self.preload(songLoc)
 
        self.pipeline.set_property("uri", songLoc)
 
        self.lastSetSongUri = songLoc
 
        self._lastSetSongUri = songLoc
 
        # todo: don't have any error report yet if the uri can't be read
 
        if play:
 
            self.pipeline.set_state(Gst.State.PLAYING)
 
            self.playStartTime = time.time()
 
            self._playStartTime = time.time()
 

	
 
    def getSong(self):
 
        """Returns the URI of the current song."""
 
        # even the 'uri' that I just set isn't readable yet
 
        return self.playbin.get_property("uri") or self.lastSetSongUri
 
        return self.playbin.get_property("uri") or self._lastSetSongUri
 

	
 
    def preload(self, songPath):
 
        """
 
        to avoid disk seek stutters, which happened sometimes (in 2007) with the
 
        non-gst version of this program, we read the whole file to get
 
        more OS caching.
 
@@ -181,14 +181,14 @@ class Player:
 
        self.pipeline.set_state(Gst.State.PLAYING)
 

	
 
    def setupAutostop(self):
 
        dur = self.duration()
 
        if dur == 0:
 
            raise ValueError("duration=0, can't set autostop")
 
        self.autoStopTime = (dur - self.autoStopOffset)
 
        log.info("autostop will be at %s", self.autoStopTime)
 
        self._autoStopTime = (dur - self.autoStopOffset)
 
        log.info("autostop will be at %s", self._autoStopTime)
 
        # pipeline.seek can take a stop time, but using that wasn't
 
        # working out well. I'd get pauses at other times that were
 
        # hard to remove.
 

	
 
    def isPlaying(self):
 
        _, state, _ = self.pipeline.get_state(timeout=0)
0 comments (0 inline, 0 general)