Esempio n. 1
0
    def pump(self):
        # Release spent buffers
        processed = al.ALint()
        al.alGetSourcei(self._al_source, al.AL_BUFFERS_PROCESSED, processed)
        processed = processed.value
        if processed:
            buffers = (al.ALuint * processed)()
            al.alSourceUnqueueBuffers(self._al_source, len(buffers), buffers)
            al.alDeleteBuffers(len(buffers), buffers)

        # Pop timestamps and check for eos markers
        try:
            while processed:
                if not _have_1_1:
                    self._timestamp_system_time = time.time()
                _, duration = self._timestamps.pop(0)
                self._buffered_time -= duration
                while self._timestamps[0][0] is None:
                    self._eos_count += 1
                    self._timestamps.pop(0)
                processed -= 1
        except IndexError:
            pass

        if _have_1_1:
            samples = al.ALint()
            al.alGetSourcei(self._al_source, al.AL_SAMPLE_OFFSET, samples)
            self._current_buffer_time = samples.value / float(self.audio_format.sample_rate)
        else:
            # Interpolate system time past buffer timestamp
            self._current_buffer_time = time.time() - self._timestamp_system_time

        # Begin playing if underrun previously
        if self._playing:
            self._al_play()
Esempio n. 2
0
    def playing(self):
        al.alGetSourcei(self.source, al.AL_SOURCE_STATE, self.state)

        if self.state.value == al.AL_PLAYING:
            return True
        else:
            return False
Esempio n. 3
0
 def _al_play(self):
     if not self._timestamps:
         return
     state = al.ALint()
     al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
     if state.value != al.AL_PLAYING:
         al.alSourcePlay(self._al_source)
Esempio n. 4
0
 def _al_play(self):
     if not self._timestamps:
         return
     state = al.ALint()
     al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
     if state.value != al.AL_PLAYING:
         al.alSourcePlay(self._al_source)
Esempio n. 5
0
    def playing(self):
        al.alGetSourcei(self.source, al.AL_SOURCE_STATE, self.state)

        if self.state.value == al.AL_PLAYING:
            return True
        else:
            return False
Esempio n. 6
0
    def get_time(self):
        state = al.ALint()
        al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
        if state.value != al.AL_PLAYING:
            return self._pause_timestamp

        if not self._timestamps:
            return self._pause_timestamp

        ts, _ = self._timestamps[0]

        return ts + self._current_buffer_time
Esempio n. 7
0
    def get_time(self):
        state = al.ALint()
        al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
        if state.value != al.AL_PLAYING:
            return self._pause_timestamp

        if not self._timestamps:
            return self._pause_timestamp

        ts, _ = self._timestamps[0]

        return ts + self._current_buffer_time
Esempio n. 8
0
    def clear(self):
        al.alSourceStop(self._al_source)
        self._playing = False

        processed = al.ALint()
        al.alGetSourcei(self._al_source, al.AL_BUFFERS_PROCESSED, processed)
        if processed.value:
            buffers = (al.ALuint * processed.value)()
            al.alSourceUnqueueBuffers(self._al_source, len(buffers), buffers)
            al.alDeleteBuffers(len(buffers), buffers)

        self._pause_timestamp = 0.0
        self._buffered_time = 0.0
        self._timestamps = []
Esempio n. 9
0
    def clear(self):
        al.alSourceStop(self._al_source)
        self._playing = False

        processed = al.ALint()
        al.alGetSourcei(self._al_source, al.AL_BUFFERS_PROCESSED, processed)
        if processed.value:
            buffers = (al.ALuint * processed.value)()
            al.alSourceUnqueueBuffers(self._al_source, len(buffers), buffers)
            al.alDeleteBuffers(len(buffers), buffers)

        self._pause_timestamp = 0.0
        self._buffered_time = 0.0
        self._timestamps = []
Esempio n. 10
0
    def _get_time(self):
        if not self._sources:
            return 0.0

        if not self._playing:
            return self._last_known_timestamp
        
        if self._sources[0].audio_format:
            if not self._al_playing:
                return self._last_known_timestamp

            # Add current buffer timestamp to sample offset within that
            # buffer.
            buffer = al.ALint()
            al.alGetSourcei(self._al_source, al.AL_BUFFER, buffer)
            if not buffer or not al.alIsBuffer(buffer.value):
                return 0.0

            # The playback position at the start of the current buffer
            buffer_timestamp = buffer_pool.info[buffer.value].timestamp

            if _have_1_1:
                # Add buffer timestamp to sample offset
                # XXX This is wrong, should consider offset into all buffers
                buffer_samples = al.ALint()
                al.alGetSourcei(self._al_source, 
                                al.AL_SAMPLE_OFFSET, buffer_samples)
                sample_rate = al.ALint()
                al.alGetBufferi(buffer.value, al.AL_FREQUENCY, sample_rate)
                buffer_time = buffer_samples.value / float(sample_rate.value)
                self._last_known_timestamp = buffer_timestamp + buffer_time
                return buffer_timestamp + buffer_time
            else:
                if buffer.value == self._last_buffer:
                    # Interpolate system time past buffer timestamp
                    return (time.time() - self._last_known_system_time + 
                            self._last_known_timestamp)
                else:
                    # Buffer has changed, assume we are at the start of it.
                    self._last_known_system_time = time.time()
                    self._last_known_timestamp = buffer_timestamp
                    self._last_buffer = buffer.value
                    return buffer_timestamp
        else:
            # There is no audio data, so we use system time to track the 
            # timestamp.
            return (time.time() - self._last_known_system_time +
                    self._last_known_timestamp)
Esempio n. 11
0
    def play(self):
        if self._playing:
            return

        self._playing = True

        if not self._sources:
            return

        if self._sources[0].al_format:
            buffers = al.ALint()
            al.alGetSourcei(self._al_source, al.AL_BUFFERS_QUEUED, buffers)
            if buffers.value:
                al.alSourcePlay(self._al_source)
                self._al_playing = True
        self._last_known_system_time = time.time()
Esempio n. 12
0
    def _clear_buffers(self):
        '''Stop source and remove all queued buffers.'''
        al.alSourceStop(self._al_source)
        self._al_playing = False

        processed = al.ALint()
        al.alGetSourcei(self._al_source, 
                        al.AL_BUFFERS_PROCESSED, processed)
        processed = processed.value

        if processed:
            buffers = (al.ALuint * processed)()
            al.alSourceUnqueueBuffers(self._al_source, 
                                      len(buffers), buffers)
            for buffer in buffers:
                info = self._queued_buffers.pop(0)
                assert info is buffer_pool.info[buffer]
                buffer_pool.release(buffer)
        assert not self._queued_buffers
Esempio n. 13
0
    def pump(self):
        # Release spent buffers
        processed = al.ALint()
        al.alGetSourcei(self._al_source, al.AL_BUFFERS_PROCESSED, processed)
        processed = processed.value
        if processed:
            buffers = (al.ALuint * processed)()
            al.alSourceUnqueueBuffers(self._al_source, len(buffers), buffers)
            al.alDeleteBuffers(len(buffers), buffers)

        # Pop timestamps and check for eos markers
        try:
            while processed:
                if not _have_1_1:
                    self._timestamp_system_time = time.time()
                _, duration = self._timestamps.pop(0)
                self._buffered_time -= duration
                while self._timestamps[0][0] is None:
                    self._eos_count += 1
                    self._timestamps.pop(0)
                processed -= 1
        except IndexError:
            pass

        if _have_1_1:
            samples = al.ALint()
            al.alGetSourcei(self._al_source, al.AL_SAMPLE_OFFSET, samples)
            self._current_buffer_time = samples.value / \
                float(self.audio_format.sample_rate)
        else:
            # Interpolate system time past buffer timestamp
            self._current_buffer_time = time.time() - \
                self._timestamp_system_time

        # Begin playing if underrun previously
        if self._playing:
            self._al_play()
Esempio n. 14
0
 def _get_seek(self):  #returns float 0.0-1.0
     al.alGetSourcei(self.source, al.AL_BYTE_OFFSET, self.state)
     return float(self.state.value) / float(self.queue[0].length)
Esempio n. 15
0
 def _get_seek(self):
     al.alGetSourcei(self.source, al.AL_BYTE_OFFSET, self.state)
     return float(self.state.value) / float(self.queue[0].length)
Esempio n. 16
0
    def dispatch_events(self):
        if not self._sources:
            return
            
        if not self._playing:
            # If paused, just update the video texture.
            if self._texture:
                self._sources[0]._update_texture(self, self.time)
            return

        # Calculate once only for this method.
        self_time = self.time
        
        # Update state of AL source
        state = al.ALint()
        al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
        self._al_playing = state.value == al.AL_PLAYING

        if self._sources[0].al_format:
            # Find out how many buffers are done
            processed = al.ALint()
            al.alGetSourcei(self._al_source, 
                            al.AL_BUFFERS_PROCESSED, processed)
            processed = processed.value
            queued = al.ALint()
            al.alGetSourcei(self._al_source, al.AL_BUFFERS_QUEUED, queued)

            # Release spent buffers
            if processed:
                buffers = (al.ALuint * processed)()
                al.alSourceUnqueueBuffers(self._al_source, 
                                          len(buffers), buffers)

                # If any buffers were EOS buffers, dispatch appropriate
                # event.
                for buffer in buffers:
                    info = self._queued_buffers.pop(0)
                    assert info is buffer_pool.info[buffer]
                    if info.is_eos:
                        if self._eos_action == self.EOS_NEXT:
                            self.next()
                        elif self._eos_action == self.EOS_STOP:
                            # For ManagedSoundPlayer only.
                            self.stop()
                        self.dispatch_event('on_eos')
                    buffer_pool.release(buffer)

        else:
            # Check for EOS on silent source
            if self_time > self._sources[0].duration:
                if self._eos_action == self.EOS_NEXT:
                    self.next()
                self.dispatch_event('on_eos')

        # Determine minimum duration of audio already buffered (current buffer
        # is ignored, as this could be just about to be dequeued).
        buffer_time = sum([b.length for b in self._queued_buffers[1:]])

        # Ensure audio buffers are full
        try:
            source = self._sources[self._source_read_index]
        except IndexError:
            source = None
        while source and buffer_time < self._min_buffer_time:
            # Read next packet of audio data
            if source.al_format:
                max_bytes = int(
                  self._min_buffer_time * source.audio_format.bytes_per_second)
                max_bytes = min(max_bytes, self._max_buffer_size)
                audio_data = source._get_audio_data(max_bytes)

            # If there is audio data, create and queue a buffer
            if source.al_format and audio_data:
                buffer = buffer_pool.get(audio_data.timestamp,
                                         audio_data.duration,
                                         buffer_pool,
                                         audio_data.is_eos)
                al.alBufferData(buffer, 
                                source.al_format,
                                audio_data.data,
                                audio_data.length,
                                source.audio_format.sample_rate)
                # TODO consolidate info and audio_data
                info = buffer_pool.info[buffer.value]
                self._queued_buffers.append(info)
                buffer_time += info.length

                # Queue this buffer onto the AL source.
                al.alSourceQueueBuffers(self._al_source, 1, 
                                        ctypes.byref(buffer))
                
            else:
                # No more data from source, check eos behaviour
                if self._eos_action == self.EOS_NEXT:
                    self._source_read_index += 1
                    try:
                        source = self._sources[self._source_read_index]
                        source._play() # Preroll source ahead of buffering
                    except IndexError:
                        source = None
                elif self._eos_action == self.EOS_LOOP:
                    source._seek(0)
                elif self._eos_action == self.EOS_PAUSE:
                    source = None
                elif self._eos_action == self.EOS_STOP:
                    source = None
                else:
                    assert False, 'Invalid eos_action'
                    source = None

        # Update video texture
        if self._texture:
            self._sources[0]._update_texture(self, self_time)


        # Ensure the AL source is playing (if there is a buffer underrun
        # this restarts the AL source).  This needs to be at the end of the
        # function to ensure it catches newly queued sources without needing
        # a second iteration of dispatch_events.
        if (self._sources and self._sources[0].al_format and
            self._queued_buffers and
            self._playing and not self._al_playing):
            al.alSourcePlay(self._al_source)
            self._al_playing = True