Add mapper

Ger rid of static ids for interfaces and replace with something we can
register dynamically
Implement logger.
This commit is contained in:
Wim Taymans 2016-10-07 13:14:32 +02:00
parent a68e5d5124
commit fc4fd1424a
43 changed files with 997 additions and 360 deletions

View file

@ -26,6 +26,8 @@
#include <libudev.h>
#include <spa/log.h>
#include <spa/id-map.h>
#include <spa/poll.h>
#include <spa/monitor.h>
#include <spa/debug.h>
@ -41,10 +43,18 @@ typedef struct {
SpaDictItem info_items[32];
} ALSAItem;
typedef struct {
uint32_t monitor;
} URI;
struct _SpaALSAMonitor {
SpaHandle handle;
SpaMonitor monitor;
URI uri;
SpaIDMap *map;
SpaLog *log;
SpaMonitorEventCallback event_cb;
void *user_data;
@ -360,13 +370,11 @@ spa_alsa_monitor_get_interface (SpaHandle *handle,
this = (SpaALSAMonitor *) handle;
switch (interface_id) {
case SPA_INTERFACE_ID_MONITOR:
*interface = &this->monitor;
break;
default:
return SPA_RESULT_UNKNOWN_INTERFACE;
}
if (interface_id == this->uri.monitor)
*interface = &this->monitor;
else
return SPA_RESULT_UNKNOWN_INTERFACE;
return SPA_RESULT_OK;
}
@ -380,10 +388,11 @@ static SpaResult
alsa_monitor_init (const SpaHandleFactory *factory,
SpaHandle *handle,
const SpaDict *info,
const SpaSupport **support,
const SpaSupport *support,
unsigned int n_support)
{
SpaALSAMonitor *this;
unsigned int i;
if (factory == NULL || handle == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -392,6 +401,19 @@ alsa_monitor_init (const SpaHandleFactory *factory,
handle->clear = alsa_monitor_clear,
this = (SpaALSAMonitor *) handle;
for (i = 0; i < n_support; i++) {
if (strcmp (support[i].uri, SPA_ID_MAP_URI) == 0)
this->map = support[i].data;
else if (strcmp (support[i].uri, SPA_LOG_URI) == 0)
this->log = support[i].data;
}
if (this->map == NULL) {
spa_log_error (this->log, "an id-map is needed");
return SPA_RESULT_ERROR;
}
this->uri.monitor = spa_id_map_get_id (this->map, SPA_MONITOR_URI);
this->monitor = alsamonitor;
this->monitor.handle = handle;
@ -400,10 +422,7 @@ alsa_monitor_init (const SpaHandleFactory *factory,
static const SpaInterfaceInfo alsa_monitor_interfaces[] =
{
{ SPA_INTERFACE_ID_MONITOR,
SPA_INTERFACE_ID_MONITOR_NAME,
SPA_INTERFACE_ID_MONITOR_DESCRIPTION,
},
{ SPA_MONITOR_URI, },
};
static SpaResult

View file

@ -579,13 +579,11 @@ spa_alsa_sink_get_interface (SpaHandle *handle,
this = (SpaALSASink *) handle;
switch (interface_id) {
case SPA_INTERFACE_ID_NODE:
*interface = &this->node;
break;
default:
return SPA_RESULT_UNKNOWN_INTERFACE;
}
if (interface_id == this->uri.node)
*interface = &this->node;
else
return SPA_RESULT_UNKNOWN_INTERFACE;
return SPA_RESULT_OK;
}
@ -599,10 +597,11 @@ static SpaResult
alsa_sink_init (const SpaHandleFactory *factory,
SpaHandle *handle,
const SpaDict *info,
const SpaSupport **support,
const SpaSupport *support,
unsigned int n_support)
{
SpaALSASink *this;
unsigned int i;
if (factory == NULL || handle == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -611,6 +610,19 @@ alsa_sink_init (const SpaHandleFactory *factory,
handle->clear = alsa_sink_clear;
this = (SpaALSASink *) handle;
for (i = 0; i < n_support; i++) {
if (strcmp (support[i].uri, SPA_ID_MAP_URI) == 0)
this->map = support[i].data;
else if (strcmp (support[i].uri, SPA_LOG_URI) == 0)
this->log = support[i].data;
}
if (this->map == NULL) {
spa_log_error (this->log, "an id-map is needed");
return SPA_RESULT_ERROR;
}
this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI);
this->node = alsasink_node;
this->node.handle = handle;
this->props[1].props.n_prop_info = PROP_ID_LAST;
@ -627,10 +639,7 @@ alsa_sink_init (const SpaHandleFactory *factory,
static const SpaInterfaceInfo alsa_sink_interfaces[] =
{
{ SPA_INTERFACE_ID_NODE,
SPA_INTERFACE_ID_NODE_NAME,
SPA_INTERFACE_ID_NODE_DESCRIPTION,
},
{ SPA_NODE_URI, },
};
static SpaResult

View file

@ -485,7 +485,7 @@ spa_alsa_source_node_port_use_buffers (SpaNode *node,
case SPA_DATA_TYPE_DMABUF:
case SPA_DATA_TYPE_MEMPTR:
if (buffers[i]->datas[0].data == NULL) {
fprintf (stderr, "alsa-source: need mapped memory\n");
spa_log_error (this->log, "alsa-source: need mapped memory\n");
continue;
}
break;
@ -729,16 +729,13 @@ spa_alsa_source_get_interface (SpaHandle *handle,
this = (SpaALSASource *) handle;
switch (interface_id) {
case SPA_INTERFACE_ID_NODE:
*interface = &this->node;
break;
case SPA_INTERFACE_ID_CLOCK:
*interface = &this->clock;
break;
default:
return SPA_RESULT_UNKNOWN_INTERFACE;
}
if (interface_id == this->uri.node)
*interface = &this->node;
else if (interface_id == this->uri.clock)
*interface = &this->clock;
else
return SPA_RESULT_UNKNOWN_INTERFACE;
return SPA_RESULT_OK;
}
@ -752,7 +749,7 @@ static SpaResult
alsa_source_init (const SpaHandleFactory *factory,
SpaHandle *handle,
const SpaDict *info,
const SpaSupport **support,
const SpaSupport *support,
unsigned int n_support)
{
SpaALSASource *this;
@ -765,6 +762,20 @@ alsa_source_init (const SpaHandleFactory *factory,
handle->clear = alsa_source_clear;
this = (SpaALSASource *) handle;
for (i = 0; i < n_support; i++) {
if (strcmp (support[i].uri, SPA_ID_MAP_URI) == 0)
this->map = support[i].data;
else if (strcmp (support[i].uri, SPA_LOG_URI) == 0)
this->log = support[i].data;
}
if (this->map == NULL) {
spa_log_error (this->log, "an id-map is needed");
return SPA_RESULT_ERROR;
}
this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI);
this->uri.clock = spa_id_map_get_id (this->map, SPA_CLOCK_URI);
this->node = alsasource_node;
this->node.handle = handle;
this->clock = alsasource_clock;
@ -790,14 +801,8 @@ alsa_source_init (const SpaHandleFactory *factory,
static const SpaInterfaceInfo alsa_source_interfaces[] =
{
{ SPA_INTERFACE_ID_NODE,
SPA_INTERFACE_ID_NODE_NAME,
SPA_INTERFACE_ID_NODE_DESCRIPTION,
},
{ SPA_INTERFACE_ID_CLOCK,
SPA_INTERFACE_ID_CLOCK_NAME,
SPA_INTERFACE_ID_CLOCK_DESCRIPTION,
},
{ SPA_NODE_URI, },
{ SPA_CLOCK_URI, },
};
static SpaResult

View file

@ -9,9 +9,7 @@
#include "alsa-utils.h"
static int verbose = 0; /* verbose flag */
#define CHECK(s,msg) if ((err = (s)) < 0) { printf (msg ": %s\n", snd_strerror(err)); return err; }
#define CHECK(s,msg) if ((err = (s)) < 0) { spa_log_error (state->log, msg ": %s\n", snd_strerror(err)); return err; }
static int
spa_alsa_open (SpaALSAState *state)
@ -24,7 +22,7 @@ spa_alsa_open (SpaALSAState *state)
CHECK (snd_output_stdio_attach (&state->output, stderr, 0), "attach failed");
printf ("ALSA device open '%s'\n", props->device);
spa_log_info (state->log, "ALSA device open '%s'\n", props->device);
CHECK (snd_pcm_open (&state->hndl,
props->device,
state->stream,
@ -46,7 +44,7 @@ spa_alsa_close (SpaALSAState *state)
if (!state->opened)
return 0;
printf ("Playback device closing\n");
spa_log_info (state->log, "Playback device closing\n");
CHECK (snd_pcm_close (state->hndl), "close failed");
state->opened = false;
@ -134,14 +132,14 @@ spa_alsa_set_format (SpaALSAState *state, SpaFormatAudio *fmt, SpaPortFormatFlag
/* set the sample format */
format = spa_alsa_format_to_alsa (info->format);
printf ("Stream parameters are %iHz, %s, %i channels\n", info->rate, snd_pcm_format_name(format), info->channels);
spa_log_info (state->log, "Stream parameters are %iHz, %s, %i channels\n", info->rate, snd_pcm_format_name(format), info->channels);
CHECK (snd_pcm_hw_params_set_format (hndl, params, format), "set_format");
/* set the count of channels */
rchannels = info->channels;
CHECK (snd_pcm_hw_params_set_channels_near (hndl, params, &rchannels), "set_channels");
if (rchannels != info->channels) {
fprintf (stderr, "Channels doesn't match (requested %u, get %u\n", info->channels, rchannels);
spa_log_info (state->log, "Channels doesn't match (requested %u, get %u\n", info->channels, rchannels);
if (flags & SPA_PORT_FORMAT_FLAG_NEAREST)
info->channels = rchannels;
else
@ -152,7 +150,7 @@ spa_alsa_set_format (SpaALSAState *state, SpaFormatAudio *fmt, SpaPortFormatFlag
rrate = info->rate;
CHECK (snd_pcm_hw_params_set_rate_near (hndl, params, &rrate, 0), "set_rate_near");
if (rrate != info->rate) {
fprintf (stderr, "Rate doesn't match (requested %iHz, get %iHz)\n", info->rate, rrate);
spa_log_info (state->log, "Rate doesn't match (requested %iHz, get %iHz)\n", info->rate, rrate);
if (flags & SPA_PORT_FORMAT_FLAG_NEAREST)
info->rate = rrate;
else
@ -220,14 +218,12 @@ set_swparams (SpaALSAState *state)
* Underrun and suspend recovery
*/
static int
xrun_recovery (snd_pcm_t *hndl, int err)
xrun_recovery (SpaALSAState *state, snd_pcm_t *hndl, int err)
{
if (verbose)
printf("stream recovery\n");
if (err == -EPIPE) { /* under-run */
err = snd_pcm_prepare(hndl);
if (err < 0)
printf("Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err));
spa_log_error (state->log, "Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err));
return 0;
} else if (err == -ESTRPIPE) {
while ((err = snd_pcm_resume(hndl)) == -EAGAIN)
@ -235,7 +231,7 @@ xrun_recovery (snd_pcm_t *hndl, int err)
if (err < 0) {
err = snd_pcm_prepare(hndl);
if (err < 0)
printf("Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err));
spa_log_error (state->log, "Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err));
}
return 0;
}
@ -265,8 +261,8 @@ mmap_write (SpaALSAState *state)
const snd_pcm_channel_area_t *my_areas;
if ((avail = snd_pcm_avail_update (hndl)) < 0) {
if ((err = xrun_recovery (hndl, avail)) < 0) {
printf ("Write error: %s\n", snd_strerror (err));
if ((err = xrun_recovery (state, hndl, avail)) < 0) {
spa_log_error (state->log, "Write error: %s\n", snd_strerror (err));
return -1;
}
}
@ -275,8 +271,8 @@ mmap_write (SpaALSAState *state)
while (size > 0) {
frames = size;
if ((err = snd_pcm_mmap_begin (hndl, &my_areas, &offset, &frames)) < 0) {
if ((err = xrun_recovery(hndl, err)) < 0) {
printf("MMAP begin avail error: %s\n", snd_strerror(err));
if ((err = xrun_recovery (state, hndl, err)) < 0) {
spa_log_error (state->log, "MMAP begin avail error: %s\n", snd_strerror(err));
return -1;
}
}
@ -287,8 +283,8 @@ mmap_write (SpaALSAState *state)
commitres = snd_pcm_mmap_commit (hndl, offset, frames);
if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
if ((err = xrun_recovery (hndl, commitres >= 0 ? -EPIPE : commitres)) < 0) {
printf("MMAP commit error: %s\n", snd_strerror(err));
if ((err = xrun_recovery (state, hndl, commitres >= 0 ? -EPIPE : commitres)) < 0) {
spa_log_error (state->log, "MMAP commit error: %s\n", snd_strerror(err));
return -1;
}
}
@ -326,7 +322,7 @@ mmap_read (SpaALSAState *state)
SPA_QUEUE_POP_HEAD (&state->free, SpaALSABuffer, next, b);
if (b == NULL) {
fprintf (stderr, "no more buffers\n");
spa_log_warn (state->log, "no more buffers\n");
} else {
dest = SPA_MEMBER (b->outbuf->datas[0].data, b->outbuf->datas[0].offset, void);
destsize = b->outbuf->datas[0].size;
@ -345,8 +341,8 @@ mmap_read (SpaALSAState *state)
while (size > 0) {
frames = size;
if ((err = snd_pcm_mmap_begin (hndl, &my_areas, &offset, &frames)) < 0) {
if ((err = xrun_recovery(hndl, err)) < 0) {
printf("MMAP begin avail error: %s\n", snd_strerror (err));
if ((err = xrun_recovery (state, hndl, err)) < 0) {
spa_log_error (state->log, "MMAP begin avail error: %s\n", snd_strerror (err));
return -1;
}
}
@ -364,8 +360,8 @@ mmap_read (SpaALSAState *state)
commitres = snd_pcm_mmap_commit (hndl, offset, frames);
if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
if ((err = xrun_recovery (hndl, commitres >= 0 ? -EPIPE : commitres)) < 0) {
printf("MMAP commit error: %s\n", snd_strerror(err));
if ((err = xrun_recovery (state, hndl, commitres >= 0 ? -EPIPE : commitres)) < 0) {
spa_log_error (state->log, "MMAP commit error: %s\n", snd_strerror(err));
return -1;
}
}
@ -409,12 +405,12 @@ alsa_on_fd_events (SpaPollNotifyData *data)
if (snd_pcm_state (hndl) == SND_PCM_STATE_XRUN ||
snd_pcm_state (hndl) == SND_PCM_STATE_SUSPENDED) {
err = snd_pcm_state (hndl) == SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE;
if ((err = xrun_recovery (hndl, err)) < 0) {
printf ("error: %s\n", snd_strerror (err));
if ((err = xrun_recovery (state, hndl, err)) < 0) {
spa_log_error (state->log, "error: %s\n", snd_strerror (err));
return -1;
}
} else {
printf("Wait for poll failed\n");
spa_log_error (state->log, "Wait for poll failed\n");
return -1;
}
}
@ -451,11 +447,11 @@ spa_alsa_start (SpaALSAState *state)
snd_pcm_dump (state->hndl, state->output);
if ((state->poll.n_fds = snd_pcm_poll_descriptors_count (state->hndl)) <= 0) {
printf ("Invalid poll descriptors count\n");
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) {
printf ("Unable to obtain poll descriptors for playback: %s\n", snd_strerror(err));
spa_log_error (state->log, "Unable to obtain poll descriptors for playback: %s\n", snd_strerror(err));
return err;
}

View file

@ -28,6 +28,8 @@ extern "C" {
#include <asoundlib.h>
#include <spa/id-map.h>
#include <spa/log.h>
#include <spa/queue.h>
#include <spa/node.h>
#include <spa/audio/format.h>
@ -54,11 +56,20 @@ struct _SpaALSABuffer {
SpaALSABuffer *next;
};
typedef struct {
uint32_t node;
uint32_t clock;
} URI;
struct _SpaALSAState {
SpaHandle handle;
SpaNode node;
SpaClock clock;
URI uri;
SpaIDMap *map;
SpaLog *log;
snd_pcm_stream_t stream;
snd_output_t *output;