mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	alsa: rework source a little in the case of slave
When we are slaved, read as much data as we have available and return this from process.
This commit is contained in:
		
							parent
							
								
									8b1e5fedc9
								
							
						
					
					
						commit
						715594c6ef
					
				
					 4 changed files with 124 additions and 100 deletions
				
			
		| 
						 | 
					@ -638,7 +638,7 @@ static int impl_node_process(struct spa_node *node)
 | 
				
			||||||
		SPA_FLAG_UNSET(b->flags, BUFFER_FLAG_OUT);
 | 
							SPA_FLAG_UNSET(b->flags, BUFFER_FLAG_OUT);
 | 
				
			||||||
		input->buffer_id = SPA_ID_INVALID;
 | 
							input->buffer_id = SPA_ID_INVALID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		spa_alsa_write(this, 0, true);
 | 
							spa_alsa_write(this, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		input->status = SPA_STATUS_OK;
 | 
							input->status = SPA_STATUS_OK;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -647,6 +647,9 @@ static int impl_node_process(struct spa_node *node)
 | 
				
			||||||
		io->buffer_id = SPA_ID_INVALID;
 | 
							io->buffer_id = SPA_ID_INVALID;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (spa_list_is_empty(&this->ready))
 | 
				
			||||||
 | 
							spa_alsa_read(this, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (spa_list_is_empty(&this->ready))
 | 
						if (spa_list_is_empty(&this->ready))
 | 
				
			||||||
		return SPA_STATUS_OK;
 | 
							return SPA_STATUS_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -549,28 +549,28 @@ static int alsa_recover(struct state *state, int err)
 | 
				
			||||||
		state->alsa_started = true;
 | 
							state->alsa_started = true;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		state->alsa_started = false;
 | 
							state->alsa_started = false;
 | 
				
			||||||
		spa_alsa_write(state, state->threshold * 2, true);
 | 
							spa_alsa_write(state, state->threshold * 2);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int get_status(struct state *state, snd_pcm_sframes_t *delay)
 | 
					static int get_status(struct state *state, snd_pcm_sframes_t *delay)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	snd_pcm_sframes_t av;
 | 
						snd_pcm_sframes_t avail;
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((av = snd_pcm_avail(state->hndl)) < 0) {
 | 
						if ((avail = snd_pcm_avail(state->hndl)) < 0) {
 | 
				
			||||||
		if ((res = alsa_recover(state, av)) < 0)
 | 
							if ((res = alsa_recover(state, avail)) < 0)
 | 
				
			||||||
			return res;
 | 
								return res;
 | 
				
			||||||
		if ((av = snd_pcm_avail(state->hndl)) < 0)
 | 
							if ((avail = snd_pcm_avail(state->hndl)) < 0)
 | 
				
			||||||
			return av;
 | 
								return avail;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (delay) {
 | 
						if (delay) {
 | 
				
			||||||
		if (state->stream == SND_PCM_STREAM_PLAYBACK)
 | 
							if (state->stream == SND_PCM_STREAM_PLAYBACK)
 | 
				
			||||||
			*delay = state->buffer_frames - av;
 | 
								*delay = state->buffer_frames - avail;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			*delay = av;
 | 
								*delay = avail;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -643,7 +643,7 @@ static int update_time(struct state *state, uint64_t nsec, snd_pcm_sframes_t del
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int spa_alsa_write(struct state *state, snd_pcm_uframes_t silence, bool start)
 | 
					int spa_alsa_write(struct state *state, snd_pcm_uframes_t silence)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	snd_pcm_t *hndl = state->hndl;
 | 
						snd_pcm_t *hndl = state->hndl;
 | 
				
			||||||
	const snd_pcm_channel_area_t *my_areas;
 | 
						const snd_pcm_channel_area_t *my_areas;
 | 
				
			||||||
| 
						 | 
					@ -670,6 +670,7 @@ int spa_alsa_write(struct state *state, snd_pcm_uframes_t silence, bool start)
 | 
				
			||||||
				state->dll.dt, nsec, delay, state->rate);
 | 
									state->dll.dt, nsec, delay, state->rate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (delay > state->threshold * 2) {
 | 
							if (delay > state->threshold * 2) {
 | 
				
			||||||
 | 
								spa_log_warn(state->log, "slave: skip period");
 | 
				
			||||||
			snd_pcm_rewind(state->hndl, state->threshold);
 | 
								snd_pcm_rewind(state->hndl, state->threshold);
 | 
				
			||||||
			delay -= state->threshold;
 | 
								delay -= state->threshold;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -759,7 +760,7 @@ again:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	state->sample_count += total_written;
 | 
						state->sample_count += total_written;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!state->alsa_started && written > 0 && start) {
 | 
						if (!state->alsa_started && total_written > 0) {
 | 
				
			||||||
		spa_log_trace(state->log, "snd_pcm_start %lu", written);
 | 
							spa_log_trace(state->log, "snd_pcm_start %lu", written);
 | 
				
			||||||
		if ((res = snd_pcm_start(hndl)) < 0) {
 | 
							if ((res = snd_pcm_start(hndl)) < 0) {
 | 
				
			||||||
			spa_log_error(state->log, "snd_pcm_start: %s", snd_strerror(res));
 | 
								spa_log_error(state->log, "snd_pcm_start: %s", snd_strerror(res));
 | 
				
			||||||
| 
						 | 
					@ -787,7 +788,6 @@ push_frames(struct state *state,
 | 
				
			||||||
		struct buffer *b;
 | 
							struct buffer *b;
 | 
				
			||||||
		struct spa_data *d;
 | 
							struct spa_data *d;
 | 
				
			||||||
		uint32_t index, offs, avail, l0, l1;
 | 
							uint32_t index, offs, avail, l0, l1;
 | 
				
			||||||
		struct spa_io_buffers *io;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		b = spa_list_first(&state->free, struct buffer, link);
 | 
							b = spa_list_first(&state->free, struct buffer, link);
 | 
				
			||||||
		spa_list_remove(&b->link);
 | 
							spa_list_remove(&b->link);
 | 
				
			||||||
| 
						 | 
					@ -820,47 +820,87 @@ push_frames(struct state *state,
 | 
				
			||||||
		d[0].chunk->stride = state->frame_size;
 | 
							d[0].chunk->stride = state->frame_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUT);
 | 
							SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUT);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		io = state->io;
 | 
					 | 
				
			||||||
		if (io != NULL && io->status != SPA_STATUS_HAVE_BUFFER) {
 | 
					 | 
				
			||||||
			io->buffer_id = b->id;
 | 
					 | 
				
			||||||
			io->status = SPA_STATUS_HAVE_BUFFER;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else {
 | 
					 | 
				
			||||||
		spa_list_append(&state->ready, &b->link);
 | 
							spa_list_append(&state->ready, &b->link);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		state->callbacks->ready(state->callbacks_data, SPA_STATUS_HAVE_BUFFER);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return total_frames;
 | 
						return total_frames;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int handle_play(struct state *state)
 | 
					
 | 
				
			||||||
 | 
					int spa_alsa_read(struct state *state, snd_pcm_uframes_t silence)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						snd_pcm_t *hndl = state->hndl;
 | 
				
			||||||
 | 
						snd_pcm_uframes_t total_read = 0, to_read;
 | 
				
			||||||
 | 
						const snd_pcm_channel_area_t *my_areas;
 | 
				
			||||||
 | 
						snd_pcm_uframes_t read, frames, offset;
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
	snd_pcm_sframes_t delay;
 | 
					 | 
				
			||||||
	uint64_t nsec;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (state->position && state->threshold != state->position->size)
 | 
						if (state->position && state->threshold != state->position->size)
 | 
				
			||||||
		state->threshold = state->position->size;
 | 
							state->threshold = state->position->size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clock_gettime(CLOCK_MONOTONIC, &state->now);
 | 
						if (state->slaved) {
 | 
				
			||||||
	if ((res = get_status(state, &delay)) < 0)
 | 
							uint64_t nsec, master;
 | 
				
			||||||
		return 0;
 | 
							snd_pcm_sframes_t delay;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nsec = SPA_TIMESPEC_TO_NSEC(&state->now);
 | 
							master = state->position->clock.position + state->position->clock.delay;
 | 
				
			||||||
	spa_log_trace_fp(state->log, "timeout %ld %"PRIu64" %"PRIu64" %"PRIi64" %d %ld", delay,
 | 
							nsec = master * SPA_NSEC_PER_SEC / state->rate;
 | 
				
			||||||
			nsec, state->next_time, nsec - state->next_time,
 | 
					
 | 
				
			||||||
			state->threshold, state->sample_count);
 | 
							if ((res = get_status(state, &delay)) < 0)
 | 
				
			||||||
 | 
								return res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ((res = update_time(state, nsec, delay, true)) < 0)
 | 
				
			||||||
 | 
								return res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spa_log_trace_fp(state->log, "slave %f %"PRIi64" %"PRIu64" %d",
 | 
				
			||||||
 | 
									state->dll.dt, nsec, delay, state->rate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (delay > state->threshold * 2) {
 | 
				
			||||||
 | 
								spa_log_trace_fp(state->log, "slave: skip period");
 | 
				
			||||||
 | 
								snd_pcm_forward(state->hndl, state->threshold);
 | 
				
			||||||
 | 
								delay -= state->threshold;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					again:
 | 
				
			||||||
 | 
						to_read = state->buffer_frames;
 | 
				
			||||||
 | 
						if ((res = snd_pcm_mmap_begin(hndl, &my_areas, &offset, &to_read)) < 0) {
 | 
				
			||||||
 | 
							spa_log_error(state->log, "snd_pcm_mmap_begin error: %s", snd_strerror(res));
 | 
				
			||||||
 | 
							return res;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						frames = SPA_MIN(to_read, state->threshold);
 | 
				
			||||||
 | 
						spa_log_trace_fp(state->log, "begin %ld %ld %d", offset, frames, state->threshold);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						read = push_frames(state, my_areas, offset, frames);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_log_trace_fp(state->log, "commit %ld %ld %"PRIi64, offset, read, state->sample_count);
 | 
				
			||||||
 | 
						total_read += read;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((res = snd_pcm_mmap_commit(hndl, offset, read)) < 0) {
 | 
				
			||||||
 | 
							spa_log_error(state->log, "snd_pcm_mmap_commit error: %s", snd_strerror(res));
 | 
				
			||||||
 | 
							if (res != -EPIPE && res != -ESTRPIPE)
 | 
				
			||||||
 | 
								return res;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						to_read -= read;
 | 
				
			||||||
 | 
						if (read > 0 && to_read >= state->threshold && !spa_list_is_empty(&state->free))
 | 
				
			||||||
 | 
							goto again;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state->sample_count += total_read;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int handle_play(struct state *state, uint64_t nsec, snd_pcm_sframes_t delay)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (delay >= state->threshold * 2) {
 | 
						if (delay >= state->threshold * 2) {
 | 
				
			||||||
		spa_log_trace(state->log, "early wakeup %ld %d", delay, state->threshold);
 | 
							spa_log_trace(state->log, "early wakeup %ld %d", delay, state->threshold);
 | 
				
			||||||
		state->next_time = nsec + (state->threshold / 2) * SPA_NSEC_PER_SEC / state->rate;
 | 
							state->next_time = nsec + (state->threshold / 2) * SPA_NSEC_PER_SEC / state->rate;
 | 
				
			||||||
		return 0;
 | 
							return -EAGAIN;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((res = update_time(state, nsec, delay, false)) < 0)
 | 
						if ((res = update_time(state, nsec, delay, false)) < 0)
 | 
				
			||||||
		return 0;
 | 
							return res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (spa_list_is_empty(&state->ready)) {
 | 
						if (spa_list_is_empty(&state->ready)) {
 | 
				
			||||||
		struct spa_io_buffers *io = state->io;
 | 
							struct spa_io_buffers *io = state->io;
 | 
				
			||||||
| 
						 | 
					@ -873,36 +913,52 @@ static int handle_play(struct state *state)
 | 
				
			||||||
			state->range->min_size = state->threshold * state->frame_size;
 | 
								state->range->min_size = state->threshold * state->frame_size;
 | 
				
			||||||
			state->range->max_size = state->threshold * state->frame_size;
 | 
								state->range->max_size = state->threshold * state->frame_size;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		state->callbacks->ready(state->callbacks_data, SPA_STATUS_NEED_BUFFER);
 | 
							res = state->callbacks->ready(state->callbacks_data, SPA_STATUS_NEED_BUFFER);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		spa_alsa_write(state, 0, true);
 | 
							res = spa_alsa_write(state, 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return res;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int handle_capture(struct state *state, uint64_t nsec, snd_pcm_sframes_t delay)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int res;
 | 
				
			||||||
 | 
						struct spa_io_buffers *io;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (delay < state->threshold) {
 | 
				
			||||||
 | 
							spa_log_trace(state->log, "early wakeup %ld %d", delay, state->threshold);
 | 
				
			||||||
 | 
							state->next_time = nsec + (state->threshold - delay) * SPA_NSEC_PER_SEC / state->rate;
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((res = update_time(state, nsec, delay, false)) < 0)
 | 
				
			||||||
 | 
							return res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((res = spa_alsa_read(state, 0)) < 0)
 | 
				
			||||||
 | 
							return res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!spa_list_is_empty(&state->ready)) {
 | 
				
			||||||
 | 
							io = state->io;
 | 
				
			||||||
 | 
							if (io != NULL && io->status != SPA_STATUS_HAVE_BUFFER) {
 | 
				
			||||||
 | 
								struct buffer *b = spa_list_first(&state->ready, struct buffer, link);
 | 
				
			||||||
 | 
								spa_list_remove(&b->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								io->buffer_id = b->id;
 | 
				
			||||||
 | 
								io->status = SPA_STATUS_HAVE_BUFFER;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							state->callbacks->ready(state->callbacks_data, SPA_STATUS_HAVE_BUFFER);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void alsa_on_playback_timeout_event(struct spa_source *source)
 | 
					static void alsa_on_timeout_event(struct spa_source *source)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct state *state = source->data;
 | 
						struct state *state = source->data;
 | 
				
			||||||
	uint64_t expire;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (state->started && read(state->timerfd, &expire, sizeof(uint64_t)) != sizeof(uint64_t))
 | 
					 | 
				
			||||||
		spa_log_warn(state->log, "error reading timerfd: %s", strerror(errno));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	handle_play(state);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	set_timeout(state, state->next_time);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void alsa_on_capture_timeout_event(struct spa_source *source)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	uint64_t expire, nsec;
 | 
					 | 
				
			||||||
	int res;
 | 
					 | 
				
			||||||
	struct state *state = source->data;
 | 
					 | 
				
			||||||
	snd_pcm_t *hndl = state->hndl;
 | 
					 | 
				
			||||||
	snd_pcm_sframes_t delay;
 | 
						snd_pcm_sframes_t delay;
 | 
				
			||||||
	snd_pcm_uframes_t total_read = 0, to_read;
 | 
						uint64_t nsec;
 | 
				
			||||||
	const snd_pcm_channel_area_t *my_areas;
 | 
						uint64_t expire;
 | 
				
			||||||
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (state->started && read(state->timerfd, &expire, sizeof(uint64_t)) != sizeof(uint64_t))
 | 
						if (state->started && read(state->timerfd, &expire, sizeof(uint64_t)) != sizeof(uint64_t))
 | 
				
			||||||
		spa_log_warn(state->log, "error reading timerfd: %s", strerror(errno));
 | 
							spa_log_warn(state->log, "error reading timerfd: %s", strerror(errno));
 | 
				
			||||||
| 
						 | 
					@ -919,42 +975,11 @@ static void alsa_on_capture_timeout_event(struct spa_source *source)
 | 
				
			||||||
			nsec, state->next_time, nsec - state->next_time,
 | 
								nsec, state->next_time, nsec - state->next_time,
 | 
				
			||||||
			state->threshold, state->sample_count);
 | 
								state->threshold, state->sample_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (delay < state->threshold) {
 | 
						if (state->stream == SND_PCM_STREAM_PLAYBACK)
 | 
				
			||||||
		spa_log_trace(state->log, "early wakeup %ld %d", delay, state->threshold);
 | 
							handle_play(state, nsec, delay);
 | 
				
			||||||
		state->next_time = nsec + (state->threshold - delay) * SPA_NSEC_PER_SEC / state->rate;
 | 
						else
 | 
				
			||||||
		goto next;
 | 
							handle_capture(state, nsec, delay);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((res = update_time(state, nsec, delay, false)) < 0)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	to_read = SPA_MIN(delay, state->threshold);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while (total_read < to_read) {
 | 
					 | 
				
			||||||
		snd_pcm_uframes_t read, frames, offset;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		frames = to_read - total_read;
 | 
					 | 
				
			||||||
		spa_log_trace_fp(state->log, "begin %ld %ld %ld %ld", offset, frames, to_read, total_read);
 | 
					 | 
				
			||||||
		if ((res = snd_pcm_mmap_begin(hndl, &my_areas, &offset, &frames)) < 0) {
 | 
					 | 
				
			||||||
			spa_log_error(state->log, "snd_pcm_mmap_begin error: %s", snd_strerror(res));
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		read = push_frames(state, my_areas, offset, frames);
 | 
					 | 
				
			||||||
		if (read < frames)
 | 
					 | 
				
			||||||
			to_read = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		spa_log_trace_fp(state->log, "commit %ld %ld", offset, read);
 | 
					 | 
				
			||||||
		if ((res = snd_pcm_mmap_commit(hndl, offset, read)) < 0) {
 | 
					 | 
				
			||||||
			spa_log_error(state->log, "snd_pcm_mmap_commit error: %s", snd_strerror(res));
 | 
					 | 
				
			||||||
			if (res != -EPIPE && res != -ESTRPIPE)
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		total_read += read;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	state->sample_count += total_read;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
next:
 | 
					 | 
				
			||||||
	set_timeout(state, state->next_time);
 | 
						set_timeout(state, state->next_time);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -999,7 +1024,7 @@ int spa_alsa_start(struct state *state)
 | 
				
			||||||
	state->old_dt = 1.0;
 | 
						state->old_dt = 1.0;
 | 
				
			||||||
	state->safety = 0.0;
 | 
						state->safety = 0.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_log_debug(state->log, "alsa %p: start %d %d", state, state->threshold, state->slaved);
 | 
						spa_log_debug(state->log, "alsa %p: start %d slave:%d", state, state->threshold, state->slaved);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	CHECK(set_swparams(state), "swparams");
 | 
						CHECK(set_swparams(state), "swparams");
 | 
				
			||||||
	snd_pcm_dump(state->hndl, state->output);
 | 
						snd_pcm_dump(state->hndl, state->output);
 | 
				
			||||||
| 
						 | 
					@ -1010,11 +1035,7 @@ int spa_alsa_start(struct state *state)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!state->slaved) {
 | 
						if (!state->slaved) {
 | 
				
			||||||
		if (state->stream == SND_PCM_STREAM_PLAYBACK) {
 | 
							state->source.func = alsa_on_timeout_event;
 | 
				
			||||||
			state->source.func = alsa_on_playback_timeout_event;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			state->source.func = alsa_on_capture_timeout_event;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		state->source.data = state;
 | 
							state->source.data = state;
 | 
				
			||||||
		state->source.fd = state->timerfd;
 | 
							state->source.fd = state->timerfd;
 | 
				
			||||||
		state->source.mask = SPA_IO_IN;
 | 
							state->source.mask = SPA_IO_IN;
 | 
				
			||||||
| 
						 | 
					@ -1026,7 +1047,7 @@ int spa_alsa_start(struct state *state)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (state->stream == SND_PCM_STREAM_PLAYBACK) {
 | 
						if (state->stream == SND_PCM_STREAM_PLAYBACK) {
 | 
				
			||||||
		state->alsa_started = false;
 | 
							state->alsa_started = false;
 | 
				
			||||||
		spa_alsa_write(state, state->threshold * 2, true);
 | 
							spa_alsa_write(state, state->threshold * 2);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		if ((err = snd_pcm_start(state->hndl)) < 0) {
 | 
							if ((err = snd_pcm_start(state->hndl)) < 0) {
 | 
				
			||||||
			spa_log_error(state->log, "snd_pcm_start: %s", snd_strerror(err));
 | 
								spa_log_error(state->log, "snd_pcm_start: %s", snd_strerror(err));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -157,8 +157,8 @@ int spa_alsa_start(struct state *state);
 | 
				
			||||||
int spa_alsa_pause(struct state *state);
 | 
					int spa_alsa_pause(struct state *state);
 | 
				
			||||||
int spa_alsa_close(struct state *state);
 | 
					int spa_alsa_close(struct state *state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int spa_alsa_write(struct state *state, snd_pcm_uframes_t silence, bool start);
 | 
					int spa_alsa_write(struct state *state, snd_pcm_uframes_t silence);
 | 
				
			||||||
 | 
					int spa_alsa_read(struct state *state, snd_pcm_uframes_t silence);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void dll_bandwidth(struct dll *dll, double bandwidth)
 | 
					static inline void dll_bandwidth(struct dll *dll, double bandwidth)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue