diff --git a/pipewire-jack b/pipewire-jack index b85b88b53..8d8ef587f 160000 --- a/pipewire-jack +++ b/pipewire-jack @@ -1 +1 @@ -Subproject commit b85b88b53d2d341bc873d4feca5ef7648e559a65 +Subproject commit 8d8ef587f5c6475df2887422bd268e5065227411 diff --git a/spa/include/spa/node/node.h b/spa/include/spa/node/node.h index 0aecc870c..65273d93c 100644 --- a/spa/include/spa/node/node.h +++ b/spa/include/spa/node/node.h @@ -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 diff --git a/spa/include/spa/utils/keys.h b/spa/include/spa/utils/keys.h index 62f85d1f0..a7b9126c3 100644 --- a/spa/include/spa/utils/keys.h +++ b/spa/include/spa/utils/keys.h @@ -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 */ diff --git a/spa/include/spa/utils/names.h b/spa/include/spa/utils/names.h index 0f7da1374..125301463 100644 --- a/spa/include/spa/utils/names.h +++ b/spa/include/spa/utils/names.h @@ -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 */ diff --git a/spa/plugins/alsa/alsa-device.c b/spa/plugins/alsa/alsa-pcm-device.c similarity index 82% rename from spa/plugins/alsa/alsa-device.c rename to spa/plugins/alsa/alsa-pcm-device.c index c08cb592b..55020cb58 100644 --- a/spa/plugins/alsa/alsa-device.c +++ b/spa/plugins/alsa/alsa-pcm-device.c @@ -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, diff --git a/spa/plugins/alsa/alsa-sink.c b/spa/plugins/alsa/alsa-pcm-sink.c similarity index 99% rename from spa/plugins/alsa/alsa-sink.c rename to spa/plugins/alsa/alsa-pcm-sink.c index b34d30aaf..7217a0763 100644 --- a/spa/plugins/alsa/alsa-sink.c +++ b/spa/plugins/alsa/alsa-pcm-sink.c @@ -35,9 +35,9 @@ #include #include -#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) diff --git a/spa/plugins/alsa/alsa-source.c b/spa/plugins/alsa/alsa-pcm-source.c similarity index 99% rename from spa/plugins/alsa/alsa-source.c rename to spa/plugins/alsa/alsa-pcm-source.c index f81b819a7..ac68be26b 100644 --- a/spa/plugins/alsa/alsa-source.c +++ b/spa/plugins/alsa/alsa-pcm-source.c @@ -35,9 +35,9 @@ #include #include -#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; } diff --git a/spa/plugins/alsa/alsa-utils.c b/spa/plugins/alsa/alsa-pcm.c similarity index 87% rename from spa/plugins/alsa/alsa-utils.c rename to spa/plugins/alsa/alsa-pcm.c index c585007ca..9c8ec760d 100644 --- a/spa/plugins/alsa/alsa-utils.c +++ b/spa/plugins/alsa/alsa-pcm.c @@ -11,7 +11,9 @@ #include #include -#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; diff --git a/spa/plugins/alsa/alsa-utils.h b/spa/plugins/alsa/alsa-pcm.h similarity index 100% rename from spa/plugins/alsa/alsa-utils.h rename to spa/plugins/alsa/alsa-pcm.h diff --git a/spa/plugins/alsa/alsa-seq-source.c b/spa/plugins/alsa/alsa-seq-source.c index 77ae55bbd..48c83e0dd 100644 --- a/spa/plugins/alsa/alsa-seq-source.c +++ b/spa/plugins/alsa/alsa-seq-source.c @@ -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) diff --git a/spa/plugins/alsa/alsa-udev.c b/spa/plugins/alsa/alsa-udev.c index e14d7d07a..7d9b64c8d 100644 --- a/spa/plugins/alsa/alsa-udev.c +++ b/spa/plugins/alsa/alsa-udev.c @@ -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; diff --git a/spa/plugins/alsa/meson.build b/spa/plugins/alsa/meson.build index f370feb29..11bf9c51e 100644 --- a/spa/plugins/alsa/meson.build +++ b/spa/plugins/alsa/meson.build @@ -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, diff --git a/src/examples/alsa-monitor.c b/src/examples/alsa-monitor.c index d8e6e04dc..e8f499859 100644 --- a/src/examples/alsa-monitor.c +++ b/src/examples/alsa-monitor.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -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; diff --git a/src/modules/module-adapter/adapter.c b/src/modules/module-adapter/adapter.c index dca264b50..f2290e00d 100644 --- a/src/modules/module-adapter/adapter.c +++ b/src/modules/module-adapter/adapter.c @@ -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); diff --git a/src/pipewire/keys.h b/src/pipewire/keys.h index 92f82f929..6bf91a763 100644 --- a/src/pipewire/keys.h +++ b/src/pipewire/keys.h @@ -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 */ diff --git a/src/pipewire/node.c b/src/pipewire/node.c index be95a9506..17e852268 100644 --- a/src/pipewire/node.c +++ b/src/pipewire/node.c @@ -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, diff --git a/src/pipewire/port.c b/src/pipewire/port.c index 2ea9e179d..a3ac4e1c1 100644 --- a/src/pipewire/port.c +++ b/src/pipewire/port.c @@ -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 };