improve properties on node and port

Rename some alsa filenames.
This commit is contained in:
Wim Taymans 2019-09-23 20:51:34 +02:00
parent 77e07e1948
commit db341a6450
17 changed files with 249 additions and 139 deletions

@ -1 +1 @@
Subproject commit b85b88b53d2d341bc873d4feca5ef7648e559a65
Subproject commit 8d8ef587f5c6475df2887422bd268e5065227411

View file

@ -663,6 +663,7 @@ struct spa_node_methods {
/** port keys */
#define SPA_KEY_PORT_NAME "port.name" /**< a port name */
#define SPA_KEY_PORT_ALIAS "port.alias" /**< a port alias */
#define SPA_KEY_PORT_MONITOR "port.monitor" /**< this port is a monitor port */
#ifdef __cplusplus

View file

@ -30,6 +30,9 @@ extern "C" {
#endif
/** for objects */
#define SPA_KEY_OBJECT_PATH "object.path" /**< a unique path to
* identity the object */
#define SPA_KEY_MEDIA_CLASS "media.class" /**< Media class
* Ex. "Audio/Device",
* "Video/Source",... */
@ -59,9 +62,13 @@ extern "C" {
/** info from alsa pcm_info */
#define SPA_KEY_API_ALSA_PCM_ID "api.alsa.pcm.id" /**< id from pcm_info */
#define SPA_KEY_API_ALSA_PCM_CARD "api.alsa.pcm.card" /**< card from pcm_info */
#define SPA_KEY_API_ALSA_PCM_NAME "api.alsa.pcm.name" /**< name from pcm_info */
#define SPA_KEY_API_ALSA_PCM_SUBNAME "api.alsa.pcm.subname" /**< subdevice_name from pcm_info */
#define SPA_KEY_API_ALSA_PCM_STREAM "api.alsa.pcm.stream" /**< stream type from pcm_info */
#define SPA_KEY_API_ALSA_PCM_CLASS "api.alsa.pcm.class" /**< class from pcm_info as string */
#define SPA_KEY_API_ALSA_PCM_DEVICE "api.alsa.pcm.device" /**< device from pcm_info */
#define SPA_KEY_API_ALSA_PCM_SUBDEVICE "api.alsa.pcm.subdevice" /**< subdevice from pcm_info */
#define SPA_KEY_API_ALSA_PCM_SUBCLASS "api.alsa.pcm.subclass" /**< subclass from pcm_info as string */
#define SPA_KEY_API_ALSA_PCM_SYNC_ID "api.alsa.pcm.sync-id" /**< sync id */

View file

@ -78,11 +78,12 @@ extern "C" {
* video.convert. */
/** keys for alsa factory names */
#define SPA_NAME_API_ALSA_ENUM_UDEV "api.alsa.enum.udev" /**< an alsa udev Device interface */
#define SPA_NAME_API_ALSA_DEVICE "api.alsa.device" /**< an alsa Device interface */
#define SPA_NAME_API_ALSA_PCM_DEVICE "api.alsa.pcm.device" /**< an alsa Device interface */
#define SPA_NAME_API_ALSA_PCM_SOURCE "api.alsa.pcm.source" /**< an alsa Node interface for
* capturing PCM */
#define SPA_NAME_API_ALSA_PCM_SINK "api.alsa.pcm.sink" /**< an alsa Node interface for
* playback PCM */
#define SPA_NAME_API_ALSA_MIDI_DEVICE "api.alsa.midi.device" /**< an alsa Midi device */
#define SPA_NAME_API_ALSA_MIDI_SOURCE "api.alsa.midi.source" /**< an alsa Node interface for
* capturing midi */

View file

@ -73,6 +73,18 @@ struct impl {
uint32_t profile;
};
static const char *get_stream(snd_pcm_info_t *pcminfo)
{
switch (snd_pcm_info_get_stream(pcminfo)) {
case SND_PCM_STREAM_PLAYBACK:
return "playback";
case SND_PCM_STREAM_CAPTURE:
return "capture";
default:
return "unknown";
}
}
static const char *get_class(snd_pcm_info_t *pcminfo)
{
switch (snd_pcm_info_get_class(pcminfo)) {
@ -103,9 +115,9 @@ static const char *get_subclass(snd_pcm_info_t *pcminfo)
static int emit_node(struct impl *this, snd_pcm_info_t *pcminfo, uint32_t id)
{
struct spa_dict_item items[7];
char device_name[128];
char sync_name[128];
struct spa_dict_item items[12];
char device_name[128], path[160];
char sync_name[128], dev[16], subdev[16], card[16];
struct spa_device_object_info info;
snd_pcm_sync_id_t sync_id;
@ -117,17 +129,27 @@ static int emit_node(struct impl *this, snd_pcm_info_t *pcminfo, uint32_t id)
info.factory_name = SPA_NAME_API_ALSA_PCM_SOURCE;
info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
snprintf(device_name, 128, "%s,%d", this->props.device, snd_pcm_info_get_device(pcminfo));
items[0] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PATH, device_name);
items[1] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_ID, snd_pcm_info_get_id(pcminfo));
items[2] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_NAME, snd_pcm_info_get_name(pcminfo));
items[3] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_SUBNAME, snd_pcm_info_get_subdevice_name(pcminfo));
items[4] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_CLASS, get_class(pcminfo));
items[5] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_SUBCLASS, get_subclass(pcminfo));
snprintf(card, sizeof(card), "%d", snd_pcm_info_get_card(pcminfo));
snprintf(dev, sizeof(dev), "%d", snd_pcm_info_get_device(pcminfo));
snprintf(subdev, sizeof(subdev), "%d", snd_pcm_info_get_subdevice(pcminfo));
snprintf(device_name, sizeof(device_name), "%s,%s", this->props.device, dev);
snprintf(path, sizeof(path), "alsa:pcm:%s", device_name);
items[0] = SPA_DICT_ITEM_INIT(SPA_KEY_OBJECT_PATH, path);
items[1] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PATH, device_name);
items[2] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_CARD, card);
items[3] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_DEVICE, dev);
items[4] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_SUBDEVICE, subdev);
items[5] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_STREAM, get_stream(pcminfo));
items[6] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_ID, snd_pcm_info_get_id(pcminfo));
items[7] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_NAME, snd_pcm_info_get_name(pcminfo));
items[8] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_SUBNAME, snd_pcm_info_get_subdevice_name(pcminfo));
items[9] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_CLASS, get_class(pcminfo));
items[10] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_SUBCLASS, get_subclass(pcminfo));
sync_id = snd_pcm_info_get_sync(pcminfo);
snprintf(sync_name, 128, "%08x:%08x:%08x:%08x",
snprintf(sync_name, sizeof(sync_name), "%08x:%08x:%08x:%08x",
sync_id.id32[0], sync_id.id32[1], sync_id.id32[2], sync_id.id32[3]);
items[6] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_SYNC_ID, sync_name);
items[11] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PCM_SYNC_ID, sync_name);
info.props = &SPA_DICT_INIT_ARRAY(items);
spa_device_emit_object_info(&this->hooks, id, &info);
@ -210,11 +232,13 @@ static int set_profile(struct impl *this, uint32_t id)
static int emit_info(struct impl *this, bool full)
{
int err = 0;
struct spa_dict_item items[10];
struct spa_dict_item items[20];
uint32_t n_items = 0;
snd_ctl_t *ctl_hndl;
snd_ctl_card_info_t *info;
struct spa_device_info dinfo;
struct spa_param_info params[2];
char path[128];
spa_log_info(this->log, "open card %s", this->props.device);
if ((err = snd_ctl_open(&ctl_hndl, this->props.device, 0)) < 0) {
@ -232,17 +256,21 @@ static int emit_info(struct impl *this, bool full)
dinfo = SPA_DEVICE_INFO_INIT();
dinfo.change_mask = SPA_DEVICE_CHANGE_MASK_PROPS;
items[0] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_API, "alsa");
items[1] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_NICK, snd_ctl_card_info_get_id(info));
items[2] = SPA_DICT_ITEM_INIT(SPA_KEY_MEDIA_CLASS, "Audio/Device");
items[3] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_PATH, (char *)this->props.device);
items[4] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_CARD_ID, snd_ctl_card_info_get_id(info));
items[5] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_CARD_COMPONENTS, snd_ctl_card_info_get_components(info));
items[6] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_CARD_DRIVER, snd_ctl_card_info_get_driver(info));
items[7] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_CARD_NAME, snd_ctl_card_info_get_name(info));
items[8] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_CARD_LONGNAME, snd_ctl_card_info_get_longname(info));
items[9] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_CARD_MIXERNAME, snd_ctl_card_info_get_mixername(info));
dinfo.props = &SPA_DICT_INIT(items, 10);
#define ADD_ITEM(key, value) items[n_items++] = SPA_DICT_ITEM_INIT(key, value)
snprintf(path, sizeof(path), "alsa:pcm:%s", this->props.device);
ADD_ITEM(SPA_KEY_OBJECT_PATH, path);
ADD_ITEM(SPA_KEY_DEVICE_API, "alsa:pcm");
ADD_ITEM(SPA_KEY_MEDIA_CLASS, "Audio/Device");
ADD_ITEM(SPA_KEY_API_ALSA_PATH, (char *)this->props.device);
ADD_ITEM(SPA_KEY_API_ALSA_CARD_ID, snd_ctl_card_info_get_id(info));
ADD_ITEM(SPA_KEY_API_ALSA_CARD_COMPONENTS, snd_ctl_card_info_get_components(info));
ADD_ITEM(SPA_KEY_API_ALSA_CARD_DRIVER, snd_ctl_card_info_get_driver(info));
ADD_ITEM(SPA_KEY_API_ALSA_CARD_NAME, snd_ctl_card_info_get_name(info));
ADD_ITEM(SPA_KEY_API_ALSA_CARD_LONGNAME, snd_ctl_card_info_get_longname(info));
ADD_ITEM(SPA_KEY_API_ALSA_CARD_MIXERNAME, snd_ctl_card_info_get_mixername(info));
dinfo.props = &SPA_DICT_INIT(items, n_items);
#undef ADD_ITEM
dinfo.change_mask |= SPA_DEVICE_CHANGE_MASK_PARAMS;
params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumProfile, SPA_PARAM_INFO_READ);
@ -495,7 +523,7 @@ impl_enum_interface_info(const struct spa_handle_factory *factory,
const struct spa_handle_factory spa_alsa_device_factory = {
SPA_VERSION_HANDLE_FACTORY,
SPA_NAME_API_ALSA_DEVICE,
SPA_NAME_API_ALSA_PCM_DEVICE,
NULL,
impl_get_size,
impl_init,

View file

@ -35,9 +35,9 @@
#include <spa/pod/filter.h>
#include <spa/debug/pod.h>
#define NAME "alsa-sink"
#define NAME "alsa-pcm-sink"
#include "alsa-utils.h"
#include "alsa-pcm.h"
#define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) == 0)

View file

@ -35,9 +35,9 @@
#include <spa/param/audio/format.h>
#include <spa/pod/filter.h>
#define NAME "alsa-source"
#define NAME "alsa-pcm-source"
#include "alsa-utils.h"
#include "alsa-pcm.h"
#define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) == 0)
@ -740,11 +740,11 @@ impl_init(const struct spa_handle_factory *factory,
}
}
if (this->data_loop == NULL) {
spa_log_error(this->log, "a data loop is needed");
spa_log_error(this->log, NAME" %p: a data loop is needed", this);
return -EINVAL;
}
if (this->data_system == NULL) {
spa_log_error(this->log, "a data system is needed");
spa_log_error(this->log, NAME" %p: a data system is needed", this);
return -EINVAL;
}

View file

@ -11,7 +11,9 @@
#include <spa/pod/filter.h>
#include <spa/support/system.h>
#include "alsa-utils.h"
#define NAME "alsa-pcm"
#include "alsa-pcm.h"
#define CHECK(s,msg) if ((err = (s)) < 0) { spa_log_error(state->log, msg ": %s", snd_strerror(err)); return err; }
@ -25,7 +27,7 @@ static int spa_alsa_open(struct state *state)
CHECK(snd_output_stdio_attach(&state->output, stderr, 0), "attach failed");
spa_log_info(state->log, "%p: ALSA device open '%s' %s", state, props->device,
spa_log_info(state->log, NAME"%p: ALSA device open '%s' %s", state, props->device,
state->stream == SND_PCM_STREAM_CAPTURE ? "capture" : "playback");
CHECK(snd_pcm_open(&state->hndl,
props->device,
@ -58,7 +60,7 @@ int spa_alsa_close(struct state *state)
if (!state->opened)
return 0;
spa_log_info(state->log, "%p: Device '%s' closing", state, state->props.device);
spa_log_info(state->log, NAME"%p: Device '%s' closing", state, state->props.device);
CHECK(snd_pcm_close(state->hndl), "close failed");
spa_system_close(state->data_system, state->timerfd);
@ -340,7 +342,7 @@ spa_alsa_enum_format(struct state *state, int seq, uint32_t start, uint32_t num,
spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_position, 0);
spa_pod_builder_push_array(&b, &f[1]);
for (j = 0; j < map->channels; j++) {
spa_log_debug(state->log, "position %zd %d", j, map->pos[j]);
spa_log_debug(state->log, NAME" %p: position %zd %d", state, j, map->pos[j]);
channel = chmap_position_to_channel(map->pos[j]);
spa_pod_builder_id(&b, channel);
}
@ -411,11 +413,11 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
/* set the sample format */
format = spa_format_to_alsa(info->format);
if (format == SND_PCM_FORMAT_UNKNOWN) {
spa_log_warn(state->log, "%p: unknown format %u", state, info->format);
spa_log_warn(state->log, NAME" %p: unknown format %u", state, info->format);
return -EINVAL;
}
spa_log_info(state->log, "%p: Stream parameters are %iHz, %s, %i channels",
spa_log_info(state->log, NAME" %p: Stream parameters are %iHz, %s, %i channels",
state, info->rate, snd_pcm_format_name(format), info->channels);
CHECK(snd_pcm_hw_params_set_format(hndl, params, format), "set_format");
@ -423,7 +425,8 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
rchannels = info->channels;
CHECK(snd_pcm_hw_params_set_channels_near(hndl, params, &rchannels), "set_channels");
if (rchannels != info->channels) {
spa_log_warn(state->log, "Channels doesn't match (requested %u, get %u", info->channels, rchannels);
spa_log_warn(state->log, NAME" %p: Channels doesn't match (requested %u, get %u",
state, info->channels, rchannels);
if (flags & SPA_NODE_PARAM_FLAG_NEAREST)
info->channels = rchannels;
else
@ -434,7 +437,8 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
rrate = info->rate;
CHECK(snd_pcm_hw_params_set_rate_near(hndl, params, &rrate, 0), "set_rate_near");
if (rrate != info->rate) {
spa_log_warn(state->log, "Rate doesn't match (requested %iHz, get %iHz)", info->rate, rrate);
spa_log_warn(state->log, NAME" %p: Rate doesn't match (requested %iHz, get %iHz)",
state, info->rate, rrate);
if (flags & SPA_NODE_PARAM_FLAG_NEAREST)
info->rate = rrate;
else
@ -454,7 +458,7 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
state->period_frames = period_size;
periods = state->buffer_frames / state->period_frames;
spa_log_info(state->log, "%p: buffer frames %lu, period frames %lu, periods %u, frame_size %zd",
spa_log_info(state->log, NAME" %p: buffer frames %lu, period frames %lu, periods %u, frame_size %zd",
state, state->buffer_frames, state->period_frames,
periods, state->frame_size);
@ -530,7 +534,8 @@ static int alsa_recover(struct state *state, int err)
snd_pcm_status_alloca(&status);
if ((res = snd_pcm_status(state->hndl, status)) < 0) {
spa_log_error(state->log, "snd_pcm_status error: %s", snd_strerror(res));
spa_log_error(state->log, NAME" %p: snd_pcm_status error: %s",
state, snd_strerror(res));
return res;
}
@ -548,7 +553,7 @@ static int alsa_recover(struct state *state, int err)
delay = SPA_TIMEVAL_TO_USEC(&diff);
missing = delay * state->rate / SPA_USEC_PER_SEC;
spa_log_error(state->log, "%p: xrun of %"PRIu64" usec %"PRIu64" %f",
spa_log_error(state->log, NAME" %p: xrun of %"PRIu64" usec %"PRIu64" %f",
state, delay, missing, state->safety);
spa_node_call_xrun(&state->callbacks,
@ -558,19 +563,22 @@ static int alsa_recover(struct state *state, int err)
break;
}
default:
spa_log_error(state->log, "recover from error state %d", st);
spa_log_error(state->log, NAME" %p: recover from error state %d",
state, st);
break;
}
if ((res = snd_pcm_recover(state->hndl, err, true)) < 0) {
spa_log_error(state->log, "snd_pcm_recover error: %s", snd_strerror(res));
spa_log_error(state->log, NAME" %p: snd_pcm_recover error: %s",
state, snd_strerror(res));
return res;
}
init_loop(state);
if (state->stream == SND_PCM_STREAM_CAPTURE) {
if ((res = snd_pcm_start(state->hndl)) < 0) {
spa_log_error(state->log, "snd_pcm_start: %s", snd_strerror(res));
spa_log_error(state->log, NAME" %p: snd_pcm_start: %s",
state, snd_strerror(res));
return res;
}
state->alsa_started = true;
@ -643,7 +651,8 @@ static int update_time(struct state *state, uint64_t nsec, snd_pcm_sframes_t del
if (state->last_threshold != state->threshold) {
int32_t diff = (int32_t) (state->last_threshold - state->threshold);
spa_log_trace(state->log, "slave:%d quantum change %d", slave, diff);
spa_log_trace(state->log, NAME" %p: slave:%d quantum change %d",
state, slave, diff);
state->next_time += diff / corr * 1e9 / state->rate;
}
@ -654,8 +663,8 @@ static int update_time(struct state *state, uint64_t nsec, snd_pcm_sframes_t del
else if (state->bw == BW_MED)
set_loop(state, BW_MIN);
spa_log_debug(state->log, "slave:%d rate:%f bw:%f del:%d target:%ld err:%f (%f %f %f)",
slave, corr, state->bw, state->delay, target,
spa_log_debug(state->log, NAME" %p: slave:%d rate:%f bw:%f del:%d target:%ld err:%f (%f %f %f)",
state, slave, corr, state->bw, state->delay, target,
err, state->z1, state->z2, state->z3);
}
@ -675,8 +684,8 @@ static int update_time(struct state *state, uint64_t nsec, snd_pcm_sframes_t del
state->clock->next_nsec = state->next_time;
}
spa_log_trace_fp(state->log, "slave:%d %"PRIu64" %f %ld %f %f %d", slave, nsec,
corr, delay, err, state->threshold * corr,
spa_log_trace_fp(state->log, NAME" %p: slave:%d %"PRIu64" %f %ld %f %f %d",
state, slave, nsec, corr, delay, err, state->threshold * corr,
state->threshold);
state->next_time += state->threshold / corr * 1e9 / state->rate;
@ -705,8 +714,8 @@ int spa_alsa_write(struct state *state, snd_pcm_uframes_t silence)
return res;
if (delay > target + state->threshold) {
spa_log_warn(state->log, "slave delay:%ld resync %f %f %f", delay,
state->z1, state->z2, state->z3);
spa_log_warn(state->log, NAME" %p: slave delay:%ld resync %f %f %f",
state, delay, state->z1, state->z2, state->z3);
init_loop(state);
state->alsa_sync = true;
}
@ -729,10 +738,12 @@ int spa_alsa_write(struct state *state, snd_pcm_uframes_t silence)
again:
frames = state->buffer_frames;
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));
spa_log_error(state->log, NAME" %p: snd_pcm_mmap_begin error: %s",
state, snd_strerror(res));
return res;
}
spa_log_trace_fp(state->log, "begin %ld %ld %d %ld", offset, frames, state->threshold, silence);
spa_log_trace_fp(state->log, NAME" %p: begin %ld %ld %d %ld",
state, offset, frames, state->threshold, silence);
silence = SPA_MIN(silence, frames);
to_write = frames;
@ -776,7 +787,7 @@ again:
spa_list_remove(&b->link);
SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUT);
state->io->buffer_id = b->id;
spa_log_trace_fp(state->log, "alsa-util %p: reuse buffer %u", state, b->id);
spa_log_trace_fp(state->log, NAME" %p: reuse buffer %u", state, b->id);
spa_node_call_reuse_buffer(&state->callbacks, 0, b->id);
@ -792,16 +803,18 @@ again:
}
if (silence > 0) {
spa_log_trace_fp(state->log, "silence %ld", silence);
spa_log_trace_fp(state->log, NAME" %p: silence %ld", state, silence);
snd_pcm_areas_silence(my_areas, off, state->channels, silence, state->format);
written += silence;
}
spa_log_trace_fp(state->log, "commit %ld %ld %"PRIi64, offset, written, state->sample_count);
spa_log_trace_fp(state->log, NAME" %p: commit %ld %ld %"PRIi64,
state, offset, written, state->sample_count);
total_written += written;
if ((res = snd_pcm_mmap_commit(hndl, offset, written)) < 0) {
spa_log_error(state->log, "snd_pcm_mmap_commit error: %s", snd_strerror(res));
spa_log_error(state->log, NAME" %p: snd_pcm_mmap_commit error: %s",
state, snd_strerror(res));
if (res != -EPIPE && res != -ESTRPIPE)
return res;
}
@ -812,9 +825,10 @@ again:
state->sample_count += total_written;
if (!state->alsa_started && total_written > 0) {
spa_log_trace(state->log, "snd_pcm_start %lu", written);
spa_log_trace(state->log, NAME" %p: snd_pcm_start %lu", state, written);
if ((res = snd_pcm_start(hndl)) < 0) {
spa_log_error(state->log, "snd_pcm_start: %s", snd_strerror(res));
spa_log_error(state->log, NAME" %p: snd_pcm_start: %s",
state, snd_strerror(res));
return res;
}
state->alsa_started = true;
@ -832,7 +846,7 @@ push_frames(struct state *state,
snd_pcm_uframes_t total_frames = 0;
if (spa_list_is_empty(&state->free)) {
spa_log_warn(state->log, "%p: no more buffers", state);
spa_log_warn(state->log, NAME" %p: no more buffers", state);
total_frames = frames;
} else if (frames > 0) {
uint8_t *src;
@ -899,8 +913,8 @@ int spa_alsa_read(struct state *state, snd_pcm_uframes_t silence)
position = state->position->clock.position;
if (state->last_position && state->last_position + state->last_duration != position) {
state->alsa_sync = true;
spa_log_warn(state->log, "discont, resync %"PRIu64" %"PRIu64" %d",
state->last_position, position, state->last_duration);
spa_log_warn(state->log, NAME" %p: discont, resync %"PRIu64" %"PRIu64" %d",
state, state->last_position, position, state->last_duration);
}
state->last_position = position;
state->last_duration = state->duration;
@ -916,13 +930,14 @@ int spa_alsa_read(struct state *state, snd_pcm_uframes_t silence)
return res;
if (delay < target) {
spa_log_warn(state->log, "slave delay:%lu resync %f %f %f", delay,
state->z1, state->z2, state->z3);
spa_log_warn(state->log, NAME" %p: slave delay:%lu resync %f %f %f",
state, delay, state->z1, state->z2, state->z3);
init_loop(state);
state->alsa_sync = true;
}
if (state->alsa_sync) {
spa_log_warn(state->log, "slave resync %ld %d %ld", delay, threshold, target);
spa_log_warn(state->log, NAME" %p: slave resync %ld %d %ld",
state, delay, threshold, target);
if (delay < target)
snd_pcm_rewind(state->hndl, target - delay);
else if (delay > target)
@ -943,19 +958,23 @@ int spa_alsa_read(struct state *state, snd_pcm_uframes_t silence)
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));
spa_log_error(state->log, NAME" %p: snd_pcm_mmap_begin error: %s",
state, snd_strerror(res));
return res;
}
spa_log_trace_fp(state->log, "begin %ld %ld %ld %d", offset, frames, to_read, state->threshold);
spa_log_trace_fp(state->log, NAME" %p: begin %ld %ld %ld %d", state,
offset, frames, to_read, state->threshold);
read = push_frames(state, my_areas, offset, frames, state->delay);
spa_log_trace_fp(state->log, "commit %ld %ld %"PRIi64, offset, read, state->sample_count);
spa_log_trace_fp(state->log, NAME" %p: commit %ld %ld %"PRIi64, state,
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));
spa_log_error(state->log, NAME" %p: snd_pcm_mmap_commit error: %s",
state, snd_strerror(res));
if (res != -EPIPE && res != -ESTRPIPE)
return res;
}
@ -971,7 +990,7 @@ static int handle_play(struct state *state, uint64_t nsec,
int res;
if (delay > target + state->last_threshold) {
spa_log_trace(state->log, "early wakeup %ld %ld", delay, target);
spa_log_trace(state->log, NAME" %p: early wakeup %ld %ld", state, delay, target);
state->next_time = nsec + (delay - target) * SPA_NSEC_PER_SEC / state->rate;
return -EAGAIN;
}
@ -982,7 +1001,7 @@ static int handle_play(struct state *state, uint64_t nsec,
if (spa_list_is_empty(&state->ready)) {
struct spa_io_buffers *io = state->io;
spa_log_trace_fp(state->log, "alsa-util %p: %d", state, io->status);
spa_log_trace_fp(state->log, NAME" %p: %d", state, io->status);
io->status = SPA_STATUS_NEED_DATA;
@ -1001,7 +1020,7 @@ static int handle_capture(struct state *state, uint64_t nsec,
struct spa_io_buffers *io;
if (delay < target) {
spa_log_trace(state->log, "early wakeup %ld %ld", delay, target);
spa_log_trace(state->log, NAME" %p: early wakeup %ld %ld", state, delay, target);
state->next_time = nsec + (target - delay) * SPA_NSEC_PER_SEC /
state->rate;
return 0;
@ -1035,7 +1054,7 @@ static void alsa_on_timeout_event(struct spa_source *source)
int res;
if (state->started && spa_system_timerfd_read(state->data_system, state->timerfd, &expire) < 0)
spa_log_warn(state->log, "error reading timerfd: %m");
spa_log_warn(state->log, NAME" %p: error reading timerfd: %m", state);
if (state->position) {
state->duration = state->position->clock.duration;
@ -1053,9 +1072,9 @@ static void alsa_on_timeout_event(struct spa_source *source)
uint64_t nsec;
spa_system_clock_gettime(state->data_system, CLOCK_MONOTONIC, &now);
nsec = SPA_TIMESPEC_TO_NSEC(&now);
spa_log_trace_fp(state->log, "timeout %lu %lu %"PRIu64" %"PRIu64" %"PRIi64" %d %"PRIi64,
delay, target, nsec, state->current_time, nsec - state->current_time,
state->threshold, state->sample_count);
spa_log_trace_fp(state->log, NAME" %p: timeout %lu %lu %"PRIu64" %"PRIu64" %"PRIi64
" %d %"PRIi64, state, delay, target, nsec, state->current_time,
nsec - state->current_time, state->threshold, state->sample_count);
}
#endif
@ -1118,7 +1137,7 @@ int spa_alsa_start(struct state *state)
state->rate_denom = state->position->clock.rate.denom;
}
else {
spa_log_warn(state->log, "alsa %p: no position set, using defaults", state);
spa_log_warn(state->log, NAME" %p: no position set, using defaults", state);
state->duration = state->props.min_latency;
state->rate_denom = state->rate;
}
@ -1129,14 +1148,15 @@ int spa_alsa_start(struct state *state)
init_loop(state);
state->safety = 0.0;
spa_log_debug(state->log, "alsa %p: start %d duration:%d rate:%d slave:%d",
spa_log_debug(state->log, NAME" %p: start %d duration:%d rate:%d slave:%d",
state, state->threshold, state->duration, state->rate_denom, state->slaved);
CHECK(set_swparams(state), "swparams");
snd_pcm_dump(state->hndl, state->output);
if ((err = snd_pcm_prepare(state->hndl)) < 0) {
spa_log_error(state->log, "snd_pcm_prepare error: %s", snd_strerror(err));
spa_log_error(state->log, NAME" %p: snd_pcm_prepare error: %s", state,
snd_strerror(err));
return err;
}
@ -1155,7 +1175,8 @@ int spa_alsa_start(struct state *state)
spa_alsa_write(state, state->threshold * 2);
} else {
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, NAME" %p: snd_pcm_start: %s", state,
snd_strerror(err));
return err;
}
state->alsa_started = true;
@ -1189,7 +1210,7 @@ int spa_alsa_reslave(struct state *state)
slaved = is_slaved(state);
if (slaved != state->slaved) {
spa_log_debug(state->log, "alsa %p: reslave %d->%d", state, state->slaved, slaved);
spa_log_debug(state->log, NAME" %p: reslave %d->%d", state, state->slaved, slaved);
state->slaved = slaved;
spa_loop_invoke(state->data_loop, do_reslave, 0, NULL, 0, true, state);
}
@ -1223,12 +1244,13 @@ int spa_alsa_pause(struct state *state)
if (!state->started)
return 0;
spa_log_debug(state->log, "alsa %p: pause", state);
spa_log_debug(state->log, NAME" %p: pause", state);
spa_loop_invoke(state->data_loop, do_remove_source, 0, NULL, 0, true, state);
if ((err = snd_pcm_drop(state->hndl)) < 0)
spa_log_error(state->log, "snd_pcm_drop %s", snd_strerror(err));
spa_log_error(state->log, NAME" %p: snd_pcm_drop %s", state,
snd_strerror(err));
state->started = false;

View file

@ -227,7 +227,7 @@ static int impl_node_send_command(void *object, const struct spa_command *comman
static const struct spa_dict_item node_info_items[] = {
{ SPA_KEY_DEVICE_API, "alsa" },
{ SPA_KEY_MEDIA_CLASS, "Audio/Source" },
{ SPA_KEY_MEDIA_CLASS, "Midi/Bridge" },
{ SPA_KEY_NODE_DRIVER, "true" },
};
@ -246,7 +246,7 @@ static inline void clean_name(char *name)
{
char *c;
for (c = name; *c; ++c) {
if (!isalnum(*c) && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')')
if (!isalnum(*c) && strchr(" /_:()", *c) == NULL)
*c = '-';
}
}
@ -256,23 +256,51 @@ static void emit_port_info(struct seq_state *this, struct seq_port *port, bool f
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
struct spa_dict_item items[2];
struct spa_dict_item items[5];
uint32_t n_items = 0;
int id;
snd_seq_port_info_t *info;
snd_seq_client_info_t *client_info;
char card[8];
char name[128];
char path[128];
char alias[128];
snd_seq_port_info_alloca(&info);
snd_seq_get_any_port_info(this->sys.hndl
, port->addr.client, port->addr.port, info);
snd_seq_get_any_port_info(this->sys.hndl,
port->addr.client, port->addr.port, info);
snd_seq_client_info_alloca(&client_info);
snd_seq_get_any_client_info(this->sys.hndl,
port->addr.client, client_info);
snprintf(name, sizeof(name), "%s:%s_%d",
snd_seq_port_info_get_name(info),
snd_seq_client_info_get_name(client_info),
port->direction == SPA_DIRECTION_OUTPUT ? "capture" : "playback",
port->addr.port);
clean_name(name);
items[0] = SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "8 bit raw midi");
items[1] = SPA_DICT_ITEM_INIT(SPA_KEY_PORT_NAME, name);
port->info.props = &SPA_DICT_INIT(items, 2);
snprintf(path, sizeof(path), "alsa:seq:%s:client_%d:%s_%d",
this->props.device,
port->addr.client,
port->direction == SPA_DIRECTION_OUTPUT ? "capture" : "playback",
port->addr.port);
clean_name(path);
snprintf(alias, sizeof(alias), "%s:%s",
snd_seq_client_info_get_name(client_info),
snd_seq_port_info_get_name(info));
clean_name(alias);
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "8 bit raw midi");
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_OBJECT_PATH, path);
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_PORT_NAME, name);
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_PORT_ALIAS, alias);
if ((id = snd_seq_client_info_get_card(client_info)) != -1) {
snprintf(card, sizeof(card), "%d", id);
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_CARD, card);
}
port->info.props = &SPA_DICT_INIT(items, n_items);
spa_node_emit_port_info(&this->hooks,
port->direction, port->id, &port->info);
@ -454,7 +482,6 @@ static void update_stream_port(struct seq_state *state, struct seq_stream *strea
init_port(state, port, addr);
}
}
}
static int on_port_info(void *data, const snd_seq_addr_t *addr, const snd_seq_port_info_t *info)

View file

@ -188,13 +188,13 @@ static int emit_object_info(struct impl *this, uint32_t id, struct udev_device *
struct spa_device_object_info info;
const char *str;
char path[32];
struct spa_dict_item items[20];
struct spa_dict_item items[22];
uint32_t n_items = 0;
info = SPA_DEVICE_OBJECT_INFO_INIT();
info.type = SPA_TYPE_INTERFACE_Device;
info.factory_name = SPA_NAME_API_ALSA_DEVICE;
info.factory_name = SPA_NAME_API_ALSA_PCM_DEVICE;
info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_FLAGS |
SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
info.flags = 0;

View file

@ -1,11 +1,11 @@
spa_alsa_sources = ['alsa.c',
'alsa-udev.c',
'alsa-device.c',
'alsa-pcm-device.c',
'alsa-pcm-sink.c',
'alsa-pcm-source.c',
'alsa-pcm.c',
'alsa-seq-source.c',
'alsa-seq.c',
'alsa-sink.c',
'alsa-source.c',
'alsa-utils.c']
'alsa-seq.c']
spa_alsa = shared_library('spa-alsa',
spa_alsa_sources,

View file

@ -33,6 +33,7 @@
#include <spa/node/node.h>
#include <spa/utils/hook.h>
#include <spa/utils/names.h>
#include <spa/utils/keys.h>
#include <spa/param/audio/format-utils.h>
#include <spa/param/props.h>
#include <spa/debug/dict.h>
@ -96,7 +97,7 @@ static struct alsa_node *alsa_create_node(struct alsa_object *obj, uint32_t id,
struct monitor *monitor = obj->monitor;
struct impl *impl = monitor->impl;
int res;
const char *str;
const char *dev, *subdev;
pw_log_debug("new node %u", id);
@ -115,26 +116,47 @@ static struct alsa_node *alsa_create_node(struct alsa_object *obj, uint32_t id,
if (obj->device_id != 0)
pw_properties_setf(node->props, PW_KEY_DEVICE_ID, "%d", obj->device_id);
if ((str = pw_properties_get(obj->props, SPA_KEY_DEVICE_NICK)) != NULL)
pw_properties_set(node->props, PW_KEY_NODE_NICK, str);
str = pw_properties_get(obj->props, SPA_KEY_DEVICE_NAME);
if (str == NULL)
str = pw_properties_get(obj->props, SPA_KEY_DEVICE_NICK);
if (str == NULL)
str = pw_properties_get(obj->props, SPA_KEY_DEVICE_ALIAS);
if (str == NULL)
str = "alsa-device";
pw_properties_setf(node->props, PW_KEY_NODE_NAME, "%s.%s", info->factory_name, str);
str = pw_properties_get(obj->props, SPA_KEY_DEVICE_DESCRIPTION);
if (str == NULL)
str = "alsa-device";
pw_properties_set(node->props, PW_KEY_NODE_DESCRIPTION, str);
pw_properties_set(node->props, "factory.name", info->factory_name);
if ((dev = pw_properties_get(node->props, SPA_KEY_API_ALSA_PCM_DEVICE)) == NULL)
dev = "0";
if ((subdev = pw_properties_get(node->props, SPA_KEY_API_ALSA_PCM_SUBDEVICE)) == NULL)
subdev = "0";
if (pw_properties_get(node->props, SPA_KEY_NODE_NAME) == NULL) {
const char *devname, *stream;
if ((devname = pw_properties_get(obj->props, SPA_KEY_DEVICE_NAME)) == NULL)
devname = "unknown";
if ((stream = pw_properties_get(node->props, SPA_KEY_API_ALSA_PCM_STREAM)) == NULL)
stream = "unknown";
pw_properties_setf(node->props, SPA_KEY_NODE_NAME, "%s.%s.%s.%s",
devname, stream, dev, subdev);
}
if (pw_properties_get(node->props, PW_KEY_NODE_DESCRIPTION) == NULL) {
const char *desc, *name = NULL;
if ((desc = pw_properties_get(obj->props, SPA_KEY_DEVICE_DESCRIPTION)) == NULL)
desc = "unknown";
name = pw_properties_get(node->props, SPA_KEY_API_ALSA_PCM_NAME);
if (name == NULL)
name = pw_properties_get(node->props, SPA_KEY_API_ALSA_PCM_ID);
if (name == NULL)
name = dev;
if (strcmp(subdev, "0")) {
pw_properties_setf(node->props, PW_KEY_NODE_DESCRIPTION, "%s (%s %s)",
desc, name, subdev);
} else if (strcmp(dev, "0")) {
pw_properties_setf(node->props, PW_KEY_NODE_DESCRIPTION, "%s (%s)",
desc, name);
} else {
pw_properties_setf(node->props, PW_KEY_NODE_DESCRIPTION, "%s",
desc);
}
}
node->monitor = monitor;
node->object = obj;
node->id = id;

View file

@ -187,7 +187,7 @@ static void node_port_init(void *data, struct pw_port *port)
const struct pw_properties *old;
enum pw_direction direction;
struct pw_properties *new;
const char *str, *node_name, *media_class;
const char *str, *path, *node_name, *media_class;
void *iface;
const struct spa_support *support;
uint32_t n_support;
@ -204,7 +204,7 @@ static void node_port_init(void *data, struct pw_port *port)
if (!is_monitor && direction != n->direction)
return;
node_name = pw_properties_get(n->props, PW_KEY_NODE_NAME);
path = pw_properties_get(n->props, PW_KEY_OBJECT_PATH);
media_class = pw_properties_get(n->props, PW_KEY_MEDIA_CLASS);
if (media_class != NULL &&
@ -230,24 +230,25 @@ static void node_port_init(void *data, struct pw_port *port)
snprintf(position, 7, "%d", port->port_id);
str = position;
}
pw_properties_setf(new, PW_KEY_PORT_NAME, "%s_%s", prefix, str);
if (direction == n->direction) {
const char *api = pw_properties_get(n->props, PW_KEY_DEVICE_API);
pw_properties_setf(new, PW_KEY_PORT_ALIAS1, "%s_pcm:%s:%s%s",
api ? api : "adapter",
node_name ? node_name : "node",
direction == PW_DIRECTION_INPUT ? "in" : "out",
str);
if (is_device) {
pw_properties_set(new, PW_KEY_PORT_PHYSICAL, "1");
pw_properties_set(new, PW_KEY_PORT_TERMINAL, "1");
}
}
if ((node_name = pw_properties_get(n->props, PW_KEY_NODE_DESCRIPTION)) == NULL &&
(node_name = pw_properties_get(n->props, PW_KEY_NODE_NICK)) == NULL &&
(node_name = pw_properties_get(n->props, PW_KEY_NODE_NAME)) == NULL) {
node_name = "node";
}
pw_properties_setf(new, PW_KEY_OBJECT_PATH, "%s:%s_%d",
path ? path : node_name, prefix, port->port_id);
pw_properties_setf(new, PW_KEY_PORT_NAME, "%s_%d", prefix, port->port_id);
pw_properties_setf(new, PW_KEY_PORT_ALIAS, "%s:%s_%s",
node_name, prefix, str);
pw_port_update_properties(port, &new->dict);
pw_properties_free(new);

View file

@ -66,6 +66,7 @@ extern "C" {
#define PW_KEY_LIBRARY_NAME_LOOP "library.name.loop" /**< name of the loop library to use */
#define PW_KEY_LIBRARY_NAME_DBUS "library.name.dbus" /**< name of the dbus library to use */
#define PW_KEY_OBJECT_PATH "object.path" /**< unique path to construct the object */
#define PW_KEY_OBJECT_ID "object.id" /**< a global object id */
#define PW_KEY_CORE_ID "core.id" /**< the core id */
@ -133,8 +134,7 @@ extern "C" {
#define PW_KEY_PORT_NAME "port.name" /**< port name */
#define PW_KEY_PORT_DIRECTION "port.direction" /**< the port direction, one of "in" or "out"
* or "control" and "notify" for control ports */
#define PW_KEY_PORT_ALIAS1 "port.alias1" /**< port alias1 */
#define PW_KEY_PORT_ALIAS2 "port.alias2" /**< port alias2 */
#define PW_KEY_PORT_ALIAS "port.alias" /**< port alias */
#define PW_KEY_PORT_PHYSICAL "port.physical" /**< if this is a physical port */
#define PW_KEY_PORT_TERMINAL "port.terminal" /**< if this port consumes the data */
#define PW_KEY_PORT_CONTROL "port.control" /**< if this port is a control port */

View file

@ -549,6 +549,7 @@ int pw_node_register(struct pw_node *this,
struct pw_core *core = this->core;
struct pw_port *port;
const char *keys[] = {
PW_KEY_OBJECT_PATH,
PW_KEY_CLIENT_ID,
PW_KEY_DEVICE_ID,
PW_KEY_NODE_DESCRIPTION,

View file

@ -679,14 +679,14 @@ int pw_port_register(struct pw_port *port,
{
struct pw_node *node = port->node;
const char *keys[] = {
PW_KEY_OBJECT_PATH,
PW_KEY_FORMAT_DSP,
PW_KEY_PORT_NAME,
PW_KEY_PORT_DIRECTION,
PW_KEY_PORT_PHYSICAL,
PW_KEY_PORT_TERMINAL,
PW_KEY_PORT_CONTROL,
PW_KEY_PORT_ALIAS1,
PW_KEY_PORT_ALIAS2,
PW_KEY_PORT_ALIAS,
NULL
};