def play(self): if _debug: print('play') driver_listener.lock() driver_listener.async_operation( pa.pa_stream_cork(self.stream, 0, pa.pa_stream_success_cb_t(0), None)) if self._ended: driver_listener.async_operation( pa.pa_stream_trigger(self.stream, pa.pa_stream_success_cb_t(0), None)) driver_listener.unlock()
def play(self): if _debug: print "play" context.lock() context.async_operation(pa.pa_stream_cork(self.stream, 0, pa.pa_stream_success_cb_t(0), None)) # If whole stream has already been written, trigger immediate # playback. if self._underflow_is_eos: context.async_operation(pa.pa_stream_trigger(self.stream, pa.pa_stream_success_cb_t(0), None)) context.unlock() self._playing = True
def play(self): if _debug: print('play') driver_listener.lock() driver_listener.async_operation( pa.pa_stream_cork(self.stream, 0, pa.pa_stream_success_cb_t(0), None) ) if self._ended: driver_listener.async_operation( pa.pa_stream_trigger(self.stream, pa.pa_stream_success_cb_t(0), None) ) driver_listener.unlock()
def play(self): if _debug: print 'play' context.lock() context.async_operation( pa.pa_stream_cork(self.stream, 0, pa.pa_stream_success_cb_t(0), None)) # If whole stream has already been written, trigger immediate # playback. if self._underflow_is_eos: context.async_operation( pa.pa_stream_trigger(self.stream, pa.pa_stream_success_cb_t(0), None)) context.unlock() self._playing = True
def stop(self): if _debug: print('stop') driver_listener.lock() driver_listener.async_operation( pa.pa_stream_cork(self.stream, 1, pa.pa_stream_success_cb_t(0), None)) driver_listener.unlock()
def stop(self): if _debug: print "stop" context.lock() context.async_operation(pa.pa_stream_cork(self.stream, 1, pa.pa_stream_success_cb_t(0), None)) context.unlock() self._playing = False
def stop(self): if _debug: print('stop') driver_listener.lock() driver_listener.async_operation( pa.pa_stream_cork(self.stream, 1, pa.pa_stream_success_cb_t(0), None) ) driver_listener.unlock()
def stop(self): if _debug: print 'stop' with context.lock: context.async_operation( pa.pa_stream_cork(self.stream, 1, pa.pa_stream_success_cb_t(0), None)) self._playing = False
def stop(self): if _debug: print 'stop' with context.lock: context.async_operation( pa.pa_stream_cork(self.stream, 1, pa.pa_stream_success_cb_t(0), None) ) self._playing = False
def play(self): if _debug: print 'play' with context.lock: context.async_operation( pa.pa_stream_cork(self.stream, 0, pa.pa_stream_success_cb_t(0), None) ) # If whole stream has already been written, trigger immediate # playback. if self._underflow_is_eos: context.async_operation( pa.pa_stream_trigger(self.stream, pa.pa_stream_success_cb_t(0), None) ) if self._buffer_underflow: self._write_cb(self.stream, None, None) self._playing = True
def _write_cb(self, stream, bytes, data): if _debug: print 'write callback: %d bytes' % bytes # Asynchronously update time if self._events: context.async_operation( pa.pa_stream_update_timing_info(self.stream, self._success_cb_func, None) ) # Grab next audio packet, or leftovers from last callback. if self._buffered_audio_data: audio_data = self._buffered_audio_data self._buffered_audio_data = None else: audio_data = self.source_group.get_audio_data(bytes) seek_flag = pa.PA_SEEK_RELATIVE if self._clear_write: if _debug: print 'seek PA_SEEK_RELATIVE_ON_READ' seek_flag = pa.PA_SEEK_RELATIVE_ON_READ self._clear_write = False # Keep writing packets until `bytes` is depleted while audio_data and bytes > 0: if _debug: print 'packet', audio_data.timestamp if _debug and audio_data.events: print 'events', audio_data.events for event in audio_data.events: event_index = self._write_index + event.timestamp * \ self.source_group.audio_format.bytes_per_second self._events.append((event_index, event)) consumption = min(bytes, audio_data.length) check( pa.pa_stream_write(self.stream, audio_data.data, consumption, pa.pa_free_cb_t(0), # Data is copied 0, seek_flag) ) seek_flag = pa.PA_SEEK_RELATIVE self._read_index_valid = True self._timestamps.append((self._write_index, audio_data.timestamp)) self._write_index += consumption self._underflow_is_eos = False if _debug: print 'write', consumption if consumption < audio_data.length: audio_data.consume(consumption, self.source_group.audio_format) self._buffered_audio_data = audio_data break bytes -= consumption if bytes > 0: audio_data = self.source_group.get_audio_data(bytes) #XXX name change if not audio_data: # Whole source group has been written. Any underflow encountered # after now is the EOS. self._underflow_is_eos = True # In case the source group wasn't long enough to prebuffer stream # to PA's satisfaction, trigger immediate playback (has no effect # if stream is already playing). if self._playing: context.async_operation( pa.pa_stream_trigger(self.stream, pa.pa_stream_success_cb_t(0), None) ) self._process_events()
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._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 try: context.lock() # Create stream self.stream = pa.pa_stream_new(context._context, str(id(self)), sample_spec, channel_map) check_not_null(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) 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) finally: context.unlock() self.set_volume(self._volume) if _debug: print 'stream ready'
def _write_cb(self, stream, bytes, data): if _debug: print 'write callback: %d bytes' % bytes # Asynchronously update time if self._events: context.async_operation( pa.pa_stream_update_timing_info(self.stream, self._success_cb_func, None)) # Grab next audio packet, or leftovers from last callback. if self._buffered_audio_data: audio_data = self._buffered_audio_data self._buffered_audio_data = None else: audio_data = self.source_group.get_audio_data(bytes) seek_flag = pa.PA_SEEK_RELATIVE if self._clear_write: if _debug: print 'seek PA_SEEK_RELATIVE_ON_READ' seek_flag = pa.PA_SEEK_RELATIVE_ON_READ self._clear_write = False # Keep writing packets until `bytes` is depleted while audio_data and bytes > 0: if _debug: print 'packet', audio_data.timestamp if _debug and audio_data.events: print 'events', audio_data.events for event in audio_data.events: event_index = self._write_index + event.timestamp * \ self.source_group.audio_format.bytes_per_second self._events.append((event_index, event)) consumption = min(bytes, audio_data.length) check( pa.pa_stream_write( self.stream, audio_data.data, consumption, pa.pa_free_cb_t(0), # Data is copied 0, seek_flag)) seek_flag = pa.PA_SEEK_RELATIVE self._read_index_valid = True self._timestamps.append((self._write_index, audio_data.timestamp)) self._write_index += consumption self._underflow_is_eos = False if _debug: print 'write', consumption if consumption < audio_data.length: audio_data.consume(consumption, self.source_group.audio_format) self._buffered_audio_data = audio_data break bytes -= consumption if bytes > 0: audio_data = self.source_group.get_audio_data( bytes) #XXX name change if not audio_data: # Whole source group has been written. Any underflow encountered # after now is the EOS. self._underflow_is_eos = True # In case the source group wasn't long enough to prebuffer stream # to PA's satisfaction, trigger immediate playback (has no effect # if stream is already playing). if self._playing: context.async_operation( pa.pa_stream_trigger(self.stream, pa.pa_stream_success_cb_t(0), None)) self._process_events()
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._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 try: context.lock() # Create stream self.stream = pa.pa_stream_new(context._context, str(id(self)), sample_spec, channel_map) check_not_null(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) finally: context.unlock() self.set_volume(self._volume) if _debug: print 'stream ready'
def __init__(self, audio_format): super().__init__(audio_format) 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 device = None buffer_attr = None flags = (pa.PA_STREAM_START_CORKED | pa.PA_STREAM_INTERPOLATE_TIMING) volume = None # TODO should expose sync_stream, since soundspace example sounds # noticeably out of sync with PA. sync_stream = None try: driver_listener.lock() self.stream = pa.pa_stream_new(context, str(id(self)), sample_spec, channel_map) check_not_null(self.stream) check( pa.pa_stream_connect_playback(self.stream, device, buffer_attr, flags, volume, sync_stream) ) finally: driver_listener.unlock() self._timestamps = list() # List of (pa_time, timestamp) self._write_time = 0.0 self._timestamp = 0.0 self._timestamp_pa_time = 0.0 self._eos_count = 0 self._ended = False self._ended_underflowed = False # Callback trampoline for success operations self._success_cb_func = pa.pa_stream_success_cb_t(self._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) # 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) driver_listener.lock() while pa.pa_stream_get_state(self.stream) == pa.PA_STREAM_CREATING: driver_listener.wait() driver_listener.unlock() if _debug: print('stream ready')
def __init__(self, audio_format): super().__init__(audio_format) 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 device = None buffer_attr = None flags = (pa.PA_STREAM_START_CORKED | pa.PA_STREAM_INTERPOLATE_TIMING) volume = None # TODO should expose sync_stream, since soundspace example sounds # noticeably out of sync with PA. sync_stream = None try: driver_listener.lock() self.stream = pa.pa_stream_new(context, str(id(self)), sample_spec, channel_map) check_not_null(self.stream) check( pa.pa_stream_connect_playback(self.stream, device, buffer_attr, flags, volume, sync_stream)) finally: driver_listener.unlock() self._timestamps = list() # List of (pa_time, timestamp) self._write_time = 0.0 self._timestamp = 0.0 self._timestamp_pa_time = 0.0 self._eos_count = 0 self._ended = False self._ended_underflowed = False # Callback trampoline for success operations self._success_cb_func = pa.pa_stream_success_cb_t(self._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) # 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) driver_listener.lock() while pa.pa_stream_get_state(self.stream) == pa.PA_STREAM_CREATING: driver_listener.wait() driver_listener.unlock() if _debug: print('stream ready')