示例#1
0
    def refill(self, write_size):
        if _debug:
            print 'refill', write_size

        self._lock.acquire()

        while write_size > self._min_buffer_size:
            audio_data = self.source_group.get_audio_data(write_size)
            if not audio_data:
                self._eos = True
                self._events.append(
                    (self._write_cursor, MediaEvent(0, 'on_eos')))
                self._events.append(
                    (self._write_cursor, MediaEvent(0, 'on_source_group_eos')))
                break

            for event in audio_data.events:
                cursor = self._write_cursor + event.timestamp * \
                    self.source_group.audio_format.bytes_per_second
                self._events.append((cursor, event))

            context.lock()
            buffer = bufferPool.getBuffer(self._al_source)
            al.alBufferData(buffer,
                            self._al_format,
                            audio_data.data,
                            audio_data.length,
                            self.source_group.audio_format.sample_rate)
            if _debug_buffers:
                error = al.alGetError()
                if error != 0:
                    print("BUFFER DATA ERROR: " + str(error))
            al.alSourceQueueBuffers(self._al_source, 1, ctypes.byref(buffer))
            if _debug_buffers:
                error = al.alGetError()
                if error != 0:
                    print("QUEUE BUFFER ERROR: " + str(error))
            context.unlock()

            self._write_cursor += audio_data.length
            self._buffer_sizes.append(audio_data.length)
            self._buffer_timestamps.append(audio_data.timestamp)
            write_size -= audio_data.length

        # Check for underrun stopping playback
        if self._playing:
            state = al.ALint()
            context.lock()
            al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
            if state.value != al.AL_PLAYING:
                if _debug:
                    print 'underrun'
                al.alSourcePlay(self._al_source)
            context.unlock()

        self._lock.release()
示例#2
0
    def refill(self, write_size):
        if _debug:
            print 'refill', write_size

        self._lock.acquire()

        while write_size > self._min_buffer_size:
            audio_data = self.source_group.get_audio_data(write_size)
            if not audio_data:
                self._eos = True
                self._events.append(
                    (self._write_cursor, MediaEvent(0, 'on_eos')))
                self._events.append(
                    (self._write_cursor, MediaEvent(0, 'on_source_group_eos')))
                break

            for event in audio_data.events:
                cursor = self._write_cursor + event.timestamp * \
                    self.source_group.audio_format.bytes_per_second
                self._events.append((cursor, event))

            context.lock()
            buffer = bufferPool.getBuffer(self._al_source)
            al.alBufferData(buffer, 
                            self._al_format,
                            audio_data.data,
                            audio_data.length,
                            self.source_group.audio_format.sample_rate)
            if _debug_buffers:
                error = al.alGetError()
                if error != 0:
                    print("BUFFER DATA ERROR: " + str(error))
            al.alSourceQueueBuffers(self._al_source, 1, ctypes.byref(buffer))
            if _debug_buffers:
                error = al.alGetError()
                if error != 0:
                    print("QUEUE BUFFER ERROR: " + str(error)) 
            context.unlock()

            self._write_cursor += audio_data.length
            self._buffer_sizes.append(audio_data.length)
            self._buffer_timestamps.append(audio_data.timestamp)
            write_size -= audio_data.length

        # Check for underrun stopping playback
        if self._playing:
            state = al.ALint()
            context.lock()
            al.alGetSourcei(self._al_source, al.AL_SOURCE_STATE, state)
            if state.value != al.AL_PLAYING:
                if _debug:
                    print 'underrun'
                al.alSourcePlay(self._al_source)
            context.unlock()

        self._lock.release()
示例#3
0
    def _update_play_cursor(self):
        if not self._al_source:
            return

        self._lock.acquire()
        context.lock()

        # 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)
            error = al.alGetError()
            if error != 0:
                if _debug_buffers:
                    print ("Source unqueue error: " + str(error))
            else:
                for b in buffers:
                    bufferPool.dequeueBuffer(self._al_source, b)
        context.unlock()

        if processed:
            if len(self._buffer_timestamps) == processed and self._buffer_timestamps[-1] is not None:
                # Underrun, take note of timestamp.
                # We check that the timestamp is not None, because otherwise
                # our source could have been cleared.
                self._underrun_timestamp = self._buffer_timestamps[-1] + self._buffer_sizes[-1] / float(
                    self.source_group.audio_format.bytes_per_second
                )
            self._buffer_cursor += sum(self._buffer_sizes[:processed])
            del self._buffer_sizes[:processed]
            del self._buffer_timestamps[:processed]

            if not context.have_1_1:
                self._buffer_system_time = time.time()

        # Update play cursor using buffer cursor + estimate into current
        # buffer
        if context.have_1_1:
            bytes = al.ALint()
            context.lock()
            al.alGetSourcei(self._al_source, al.AL_BYTE_OFFSET, bytes)
            context.unlock()
            if _debug:
                print "got bytes offset", bytes.value
            self._play_cursor = self._buffer_cursor + bytes.value
        else:
            # Interpolate system time past buffer timestamp
            self._play_cursor = self._buffer_cursor + int(
                (time.time() - self._buffer_system_time) * self.source_group.audio_format.bytes_per_second
            )

        # Process events
        while self._events and self._events[0][0] < self._play_cursor:
            _, event = self._events.pop(0)
            event._sync_dispatch_to_player(self.player)

        self._lock.release()
示例#4
0
    def delete(self):
        if _debug:
            print 'OpenALAudioPlayer.delete()'

        if not self._al_source:
            return

        context.worker.remove(self)

        with self._lock:
            with context.lock:
                al.alDeleteSources(1, self._al_source)
                bufferPool.deleteSource(self._al_source)
                if _debug_buffers:
                    error = al.alGetError()
                    if error != 0:
                        print("DELETE ERROR: " + str(error))
            self._al_source = None
示例#5
0
    def delete(self):
        if _debug:
            print 'OpenALAudioPlayer.delete()'

        if not self._al_source:
            return

        context.worker.remove(self)

        with self._lock:
            with context.lock:
                al.alDeleteSources(1, self._al_source)
                bufferPool.deleteSource(self._al_source)
                if _debug_buffers:
                    error = al.alGetError()
                    if error != 0:
                        print("DELETE ERROR: " + str(error))
            self._al_source = None
示例#6
0
    def delete(self):
        if _debug:
            print "OpenALAudioPlayer.delete()"

        if not self._al_source:
            return

        context.worker.remove(self)

        self._lock.acquire()

        context.lock()

        al.alDeleteSources(1, self._al_source)
        bufferPool.deleteSource(self._al_source)
        if _debug_buffers:
            error = al.alGetError()
            if error != 0:
                print ("DELETE ERROR: " + str(error))
        context.unlock()
        self._al_source = None

        self._lock.release()
示例#7
0
 def getBuffers(self, alSource, i):
     """Returns an array containing i buffer names.  The returned list must
     not be modified in any way, and may get changed by subsequent 
     calls to getBuffers.
     """
     assert context._lock.locked()
     buffs = []
     try:
         while i > 0:
             b = self._buffers.pop()
             if not al.alIsBuffer(b):
                 # Protect against implementations that DO free buffers
                 # when they delete a source - carry on.
                 if _debug_buffers:
                     print("Found a bad buffer")
                 continue
             buffs.append(b)
             i -= 1
     except IndexError:
         while i > 0:
             buffer = al.ALuint()
             al.alGenBuffers(1, buffer)
             if _debug_buffers:
                 error = al.alGetError()
                 if error != 0:
                     print("GEN BUFFERS: " + str(error))
             buffs.append(buffer)
             i -= 1
             
     alSourceVal = alSource.value
     if alSourceVal not in self._sources:
         self._sources[alSourceVal] = buffs
     else:
         self._sources[alSourceVal].extend(buffs)
             
     return buffs
示例#8
0
    def getBuffers(self, alSource, i):
        """Returns an array containing i buffer names.  The returned list must
        not be modified in any way, and may get changed by subsequent calls to
        getBuffers.
        """
        assert context._lock.locked()
        buffs = []
        try:
            while i > 0:
                b = self._buffers.pop()
                if not al.alIsBuffer(b):
                    # Protect against implementations that DO free buffers
                    # when they delete a source - carry on.
                    if _debug_buffers:
                        print("Found a bad buffer")
                    continue
                buffs.append(b)
                i -= 1
        except IndexError:
            while i > 0:
                buffer = al.ALuint()
                al.alGenBuffers(1, buffer)
                if _debug_buffers:
                    error = al.alGetError()
                    if error != 0:
                        print("GEN BUFFERS: " + str(error))
                buffs.append(buffer)
                i -= 1

        alSourceVal = alSource.value
        if alSourceVal not in self._sources:
            self._sources[alSourceVal] = buffs
        else:
            self._sources[alSourceVal].extend(buffs)

        return buffs
示例#9
0
    def _update_play_cursor(self):
        if not self._al_source:
            return

        self._lock.acquire()
        context.lock()

        # 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)
            error = al.alGetError()
            if error != 0:
                if _debug_buffers:
                    print("Source unqueue error: " + str(error))
            else:
                for b in buffers:
                    bufferPool.dequeueBuffer(self._al_source, b)
        context.unlock()

        if processed:
            if (len(self._buffer_timestamps) == processed
                    and self._buffer_timestamps[-1] is not None):
                # Underrun, take note of timestamp.
                # We check that the timestamp is not None, because otherwise
                # our source could have been cleared.
                self._underrun_timestamp = \
                    self._buffer_timestamps[-1] + \
                    self._buffer_sizes[-1] / \
                        float(self.source_group.audio_format.bytes_per_second)
            self._buffer_cursor += sum(self._buffer_sizes[:processed])
            del self._buffer_sizes[:processed]
            del self._buffer_timestamps[:processed]

            if not context.have_1_1:
                self._buffer_system_time = time.time()

        # Update play cursor using buffer cursor + estimate into current
        # buffer
        if context.have_1_1:
            bytes = al.ALint()
            context.lock()
            al.alGetSourcei(self._al_source, al.AL_BYTE_OFFSET, bytes)
            context.unlock()
            if _debug:
                print 'got bytes offset', bytes.value
            self._play_cursor = self._buffer_cursor + bytes.value
        else:
            # Interpolate system time past buffer timestamp
            self._play_cursor = \
                self._buffer_cursor + int(
                    (time.time() - self._buffer_system_time) * \
                        self.source_group.audio_format.bytes_per_second)

        # Process events
        while self._events and self._events[0][0] < self._play_cursor:
            _, event = self._events.pop(0)
            event._sync_dispatch_to_player(self.player)

        self._lock.release()