mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
cleanups:
Keep lock while doing recycle_buffer Pass context to main loop Recycle WorkItems in a free list Push and pull from the node data loop Do async start/pause in alsa Add alsa fds right after open.
This commit is contained in:
parent
73e6272488
commit
4148e0ff78
12 changed files with 312 additions and 87 deletions
|
|
@ -170,7 +170,7 @@ spa_alsa_sink_node_send_command (SpaNode *node,
|
|||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
break;
|
||||
case SPA_NODE_COMMAND_PAUSE:
|
||||
spa_alsa_stop (this);
|
||||
spa_alsa_pause (this);
|
||||
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ update_state (SpaALSASource *this, SpaNodeState state)
|
|||
}
|
||||
|
||||
static const char default_device[] = "hw:0";
|
||||
static const uint32_t default_buffer_time = 100000;
|
||||
static const uint32_t default_period_time = 10000;
|
||||
static const uint32_t default_buffer_time = 1000;
|
||||
static const uint32_t default_period_time = 100;
|
||||
static const bool default_period_event = 0;
|
||||
|
||||
static void
|
||||
|
|
@ -151,9 +151,86 @@ spa_alsa_source_node_set_props (SpaNode *node,
|
|||
return res;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
do_send_event (SpaPoll *poll,
|
||||
bool async,
|
||||
uint32_t seq,
|
||||
size_t size,
|
||||
void *data,
|
||||
void *user_data)
|
||||
{
|
||||
SpaALSASource *this = user_data;
|
||||
|
||||
this->event_cb (&this->node, data, this->user_data);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
do_start (SpaPoll *poll,
|
||||
bool async,
|
||||
uint32_t seq,
|
||||
size_t size,
|
||||
void *data,
|
||||
void *user_data)
|
||||
{
|
||||
SpaALSASource *this = user_data;
|
||||
SpaResult res;
|
||||
SpaNodeEventAsyncComplete ac;
|
||||
|
||||
if (SPA_RESULT_IS_OK (res = spa_alsa_start (this))) {
|
||||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
}
|
||||
|
||||
if (async) {
|
||||
ac.event.type = SPA_NODE_EVENT_TYPE_ASYNC_COMPLETE;
|
||||
ac.event.size = sizeof (SpaNodeEventAsyncComplete);
|
||||
ac.seq = seq;
|
||||
ac.res = res;
|
||||
spa_poll_invoke (this->main_loop,
|
||||
do_send_event,
|
||||
SPA_ID_INVALID,
|
||||
sizeof (ac),
|
||||
&ac,
|
||||
this);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
do_pause (SpaPoll *poll,
|
||||
bool async,
|
||||
uint32_t seq,
|
||||
size_t size,
|
||||
void *data,
|
||||
void *user_data)
|
||||
{
|
||||
SpaALSASource *this = user_data;
|
||||
SpaResult res;
|
||||
SpaNodeEventAsyncComplete ac;
|
||||
|
||||
if (SPA_RESULT_IS_OK (res = spa_alsa_pause (this))) {
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
}
|
||||
|
||||
if (async) {
|
||||
ac.event.type = SPA_NODE_EVENT_TYPE_ASYNC_COMPLETE;
|
||||
ac.event.size = sizeof (SpaNodeEventAsyncComplete);
|
||||
ac.seq = seq;
|
||||
ac.res = res;
|
||||
spa_poll_invoke (this->main_loop,
|
||||
do_send_event,
|
||||
SPA_ID_INVALID,
|
||||
sizeof (ac),
|
||||
&ac,
|
||||
this);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
spa_alsa_source_node_send_command (SpaNode *node,
|
||||
SpaNodeCommand *command)
|
||||
SpaNodeCommand *command)
|
||||
{
|
||||
SpaALSASource *this;
|
||||
|
||||
|
|
@ -167,17 +244,36 @@ spa_alsa_source_node_send_command (SpaNode *node,
|
|||
return SPA_RESULT_INVALID_COMMAND;
|
||||
|
||||
case SPA_NODE_COMMAND_START:
|
||||
if (spa_alsa_start (this) < 0)
|
||||
return SPA_RESULT_ERROR;
|
||||
{
|
||||
if (!this->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
break;
|
||||
if (this->n_buffers == 0)
|
||||
return SPA_RESULT_NO_BUFFERS;
|
||||
|
||||
return spa_poll_invoke (this->data_loop,
|
||||
do_start,
|
||||
++this->seq,
|
||||
0,
|
||||
NULL,
|
||||
this);
|
||||
|
||||
}
|
||||
case SPA_NODE_COMMAND_PAUSE:
|
||||
if (spa_alsa_stop (this) < 0)
|
||||
return SPA_RESULT_ERROR;
|
||||
{
|
||||
if (!this->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
break;
|
||||
if (this->n_buffers == 0)
|
||||
return SPA_RESULT_NO_BUFFERS;
|
||||
|
||||
return spa_poll_invoke (this->data_loop,
|
||||
do_pause,
|
||||
++this->seq,
|
||||
0,
|
||||
NULL,
|
||||
this);
|
||||
}
|
||||
case SPA_NODE_COMMAND_FLUSH:
|
||||
case SPA_NODE_COMMAND_DRAIN:
|
||||
case SPA_NODE_COMMAND_MARKER:
|
||||
|
|
@ -345,8 +441,10 @@ spa_alsa_source_node_port_set_format (SpaNode *node,
|
|||
return SPA_RESULT_INVALID_PORT;
|
||||
|
||||
if (format == NULL) {
|
||||
this->have_format = false;
|
||||
spa_alsa_pause (this);
|
||||
spa_alsa_clear_buffers (this);
|
||||
spa_alsa_close (this);
|
||||
this->have_format = false;
|
||||
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -768,6 +866,8 @@ alsa_source_init (const SpaHandleFactory *factory,
|
|||
this->log = support[i].data;
|
||||
else if (strcmp (support[i].uri, SPA_POLL__DataLoop) == 0)
|
||||
this->data_loop = support[i].data;
|
||||
else if (strcmp (support[i].uri, SPA_POLL__MainLoop) == 0)
|
||||
this->main_loop = support[i].data;
|
||||
}
|
||||
if (this->map == NULL) {
|
||||
spa_log_error (this->log, "an id-map is needed");
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#define CHECK(s,msg) if ((err = (s)) < 0) { spa_log_error (state->log, msg ": %s\n", snd_strerror(err)); return err; }
|
||||
|
||||
static int alsa_on_fd_events (SpaPollNotifyData *data);
|
||||
|
||||
static int
|
||||
spa_alsa_open (SpaALSAState *state)
|
||||
{
|
||||
|
|
@ -31,12 +33,30 @@ spa_alsa_open (SpaALSAState *state)
|
|||
SND_PCM_NO_AUTO_CHANNELS |
|
||||
SND_PCM_NO_AUTO_FORMAT), "open failed");
|
||||
|
||||
if ((state->poll.n_fds = snd_pcm_poll_descriptors_count (state->hndl)) <= 0) {
|
||||
spa_log_error (state->log, "Invalid poll descriptors count %d\n", state->poll.n_fds);
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
if ((err = snd_pcm_poll_descriptors (state->hndl, (struct pollfd *)state->fds, state->poll.n_fds)) < 0) {
|
||||
spa_log_error (state->log, "Unable to obtain poll descriptors for playback: %s\n", snd_strerror(err));
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
|
||||
state->poll.id = 0;
|
||||
state->poll.enabled = false;
|
||||
state->poll.fds = state->fds;
|
||||
state->poll.idle_cb = NULL;
|
||||
state->poll.before_cb = NULL;
|
||||
state->poll.after_cb = alsa_on_fd_events;
|
||||
state->poll.user_data = state;
|
||||
spa_poll_add_item (state->data_loop, &state->poll);
|
||||
|
||||
state->opened = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
spa_alsa_close (SpaALSAState *state)
|
||||
{
|
||||
int err = 0;
|
||||
|
|
@ -44,7 +64,9 @@ spa_alsa_close (SpaALSAState *state)
|
|||
if (!state->opened)
|
||||
return 0;
|
||||
|
||||
spa_log_info (state->log, "Playback device closing\n");
|
||||
spa_poll_remove_item (state->data_loop, &state->poll);
|
||||
|
||||
spa_log_info (state->log, "Device closing\n");
|
||||
CHECK (snd_pcm_close (state->hndl), "close failed");
|
||||
|
||||
state->opened = false;
|
||||
|
|
@ -426,54 +448,41 @@ alsa_on_fd_events (SpaPollNotifyData *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
SpaResult
|
||||
spa_alsa_start (SpaALSAState *state)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (spa_alsa_open (state) < 0)
|
||||
return -1;
|
||||
|
||||
if (state->n_buffers == 0)
|
||||
return -1;
|
||||
if (state->started)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
CHECK (set_swparams (state), "swparams");
|
||||
|
||||
snd_pcm_dump (state->hndl, state->output);
|
||||
|
||||
if ((state->poll.n_fds = snd_pcm_poll_descriptors_count (state->hndl)) <= 0) {
|
||||
spa_log_error (state->log, "Invalid poll descriptors count\n");
|
||||
return state->poll.n_fds;
|
||||
}
|
||||
if ((err = snd_pcm_poll_descriptors (state->hndl, (struct pollfd *)state->fds, state->poll.n_fds)) < 0) {
|
||||
spa_log_error (state->log, "Unable to obtain poll descriptors for playback: %s\n", snd_strerror(err));
|
||||
return err;
|
||||
if (state->stream == SND_PCM_STREAM_PLAYBACK) {
|
||||
mmap_write (state);
|
||||
}
|
||||
|
||||
state->poll.id = 0;
|
||||
state->poll.enabled = true;
|
||||
state->poll.fds = state->fds;
|
||||
state->poll.idle_cb = NULL;
|
||||
state->poll.before_cb = NULL;
|
||||
state->poll.after_cb = alsa_on_fd_events;
|
||||
state->poll.user_data = state;
|
||||
spa_poll_add_item (state->data_loop, &state->poll);
|
||||
spa_poll_update_item (state->data_loop, &state->poll);
|
||||
|
||||
mmap_write (state);
|
||||
err = snd_pcm_start (state->hndl);
|
||||
state->started = true;
|
||||
|
||||
return err;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
int
|
||||
spa_alsa_stop (SpaALSAState *state)
|
||||
SpaResult
|
||||
spa_alsa_pause (SpaALSAState *state)
|
||||
{
|
||||
if (!state->opened)
|
||||
return 0;
|
||||
if (!state->started)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
state->poll.enabled = false;
|
||||
spa_poll_update_item (state->data_loop, &state->poll);
|
||||
|
||||
spa_poll_remove_item (state->data_loop, &state->poll);
|
||||
snd_pcm_drop (state->hndl);
|
||||
spa_alsa_close (state);
|
||||
state->started = false;
|
||||
|
||||
return 0;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,9 +66,12 @@ struct _SpaALSAState {
|
|||
SpaNode node;
|
||||
SpaClock clock;
|
||||
|
||||
uint32_t seq;
|
||||
|
||||
URI uri;
|
||||
SpaIDMap *map;
|
||||
SpaLog *log;
|
||||
SpaPoll *main_loop;
|
||||
SpaPoll *data_loop;
|
||||
|
||||
snd_pcm_stream_t stream;
|
||||
|
|
@ -104,7 +107,7 @@ struct _SpaALSAState {
|
|||
SpaQueue free;
|
||||
SpaQueue ready;
|
||||
|
||||
bool running;
|
||||
bool started;
|
||||
SpaPollFd fds[16];
|
||||
SpaPollItem poll;
|
||||
|
||||
|
|
@ -117,8 +120,9 @@ int spa_alsa_set_format (SpaALSAState *state,
|
|||
SpaFormatAudio *fmt,
|
||||
SpaPortFormatFlags flags);
|
||||
|
||||
int spa_alsa_start (SpaALSAState *state);
|
||||
int spa_alsa_stop (SpaALSAState *state);
|
||||
SpaResult spa_alsa_start (SpaALSAState *state);
|
||||
SpaResult spa_alsa_pause (SpaALSAState *state);
|
||||
SpaResult spa_alsa_close (SpaALSAState *state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue