Ejemplo n.º 1
0
    def delete(self):
        if _debug:
            print('delete')
        if not self.stream:
            return

        with context.lock:
            pa.pa_stream_disconnect(self.stream)

        # Wait for stream to terminate before continuing. Prevents cleaned up callbacks to be
        # called
        while pa.pa_stream_get_state(self.stream) != pa.PA_STREAM_TERMINATED:
            context.wait()

        pa.pa_stream_unref(self.stream)
        self.stream = None
Ejemplo n.º 2
0
    def __init__(self, source_group, player):
        super(PulseAudioPlayer, self).__init__(source_group, player)

        self._events = []
        self._timestamps = []  # List of (ref_time, timestamp)
        self._write_index = 0  # Current write index (tracked manually)
        self._read_index_valid = False  # True only if buffer has non-stale data

        self._clear_write = False
        self._buffered_audio_data = None
        self._underflow_is_eos = False
        self._buffer_underflow = False
        self._playing = False

        audio_format = source_group.audio_format
        assert audio_format

        # Create sample_spec
        sample_spec = pa.pa_sample_spec()
        if audio_format.sample_size == 8:
            sample_spec.format = pa.PA_SAMPLE_U8
        elif audio_format.sample_size == 16:
            if sys.byteorder == 'little':
                sample_spec.format = pa.PA_SAMPLE_S16LE
            else:
                sample_spec.format = pa.PA_SAMPLE_S16BE
        else:
            raise MediaException('Unsupported sample size')
        sample_spec.rate = audio_format.sample_rate
        sample_spec.channels = audio_format.channels
        channel_map = None
        self.sample_rate = audio_format.sample_rate

        with context.lock:
            # Create stream
            self.stream = pa.pa_stream_new(context._context,
                                           str(id(self)).encode('ASCII'),
                                           sample_spec,
                                           channel_map)
            check_not_null(self.stream)
            pa.pa_stream_ref(self.stream)

            # Callback trampoline for success operations
            self._success_cb_func = pa.pa_stream_success_cb_t(self._success_cb)
            self._context_success_cb_func = \
                pa.pa_context_success_cb_t(self._context_success_cb)

            # Callback for underflow (to detect EOS when expected pa_timestamp
            # does not get reached).
            self._underflow_cb_func = \
                pa.pa_stream_notify_cb_t(self._underflow_cb)
            pa.pa_stream_set_underflow_callback(self.stream,
                                                self._underflow_cb_func, None)

            # Callback for data write
            self._write_cb_func = pa.pa_stream_request_cb_t(self._write_cb)
            pa.pa_stream_set_write_callback(self.stream,
                                            self._write_cb_func, None)

            # Connect to sink
            device = None
            buffer_attr = None
            flags = (pa.PA_STREAM_START_CORKED |
                     pa.PA_STREAM_INTERPOLATE_TIMING |
                     pa.PA_STREAM_VARIABLE_RATE)

            sync_stream = None  # TODO use this
            check(
                pa.pa_stream_connect_playback(self.stream,
                                              device,
                                              buffer_attr,
                                              flags,
                                              None,
                                              sync_stream)
            )

            # Wait for stream readiness
            self._state_cb_func = pa.pa_stream_notify_cb_t(self._state_cb)
            pa.pa_stream_set_state_callback(self.stream,
                                            self._state_cb_func, None)
            while pa.pa_stream_get_state(self.stream) == pa.PA_STREAM_CREATING:
                context.wait()

            if pa.pa_stream_get_state(self.stream) != pa.PA_STREAM_READY:
                check(-1)

        if _debug:
            print('stream ready')