diff --git a/spa/plugins/alsa/alsa-seq-bridge.c b/spa/plugins/alsa/alsa-seq-bridge.c index f02c985fd..748b4fd5c 100644 --- a/spa/plugins/alsa/alsa-seq-bridge.c +++ b/spa/plugins/alsa/alsa-seq-bridge.c @@ -928,6 +928,8 @@ impl_init(const struct spa_handle_factory *factory, reset_props(&this->props); this->quantum_limit = 8192; + this->min_pool_size = 500; + this->max_pool_size = 2000; for (i = 0; info && i < info->n_items; i++) { const char *k = info->items[i].key; @@ -942,6 +944,10 @@ impl_init(const struct spa_handle_factory *factory, spa_atou32(s, &this->quantum_limit, 0); } else if (spa_streq(k, SPA_KEY_API_ALSA_DISABLE_LONGNAME)) { this->props.disable_longname = spa_atob(s); + } else if (spa_streq(k, "api.alsa.seq.min-pool")) { + spa_atou32(s, &this->min_pool_size, 0); + } else if (spa_streq(k, "api.alsa.seq.max-pool")) { + spa_atou32(s, &this->max_pool_size, 0); } } @@ -978,7 +984,14 @@ impl_enum_interface_info(const struct spa_handle_factory *factory, static const struct spa_dict_item info_items[] = { { SPA_KEY_FACTORY_AUTHOR, "Wim Taymans " }, { SPA_KEY_FACTORY_DESCRIPTION, "Bridge midi ports with the alsa sequencer API" }, - { SPA_KEY_FACTORY_USAGE, "["SPA_KEY_API_ALSA_PATH"=]" }, + { SPA_KEY_FACTORY_USAGE, + "["SPA_KEY_API_ALSA_PATH"=] " + "[ clock.name=] " + "[ clock.quantum-limit=] " + "["SPA_KEY_API_ALSA_DISABLE_LONGNAME"=] " + "[ api.alsa.seq.min-pool=] " + "[ api.alsa.seq.max-pool=]" + }, }; static const struct spa_dict info = SPA_DICT_INIT_ARRAY(info_items); diff --git a/spa/plugins/alsa/alsa-seq.c b/spa/plugins/alsa/alsa-seq.c index 278458e7b..f19b5720c 100644 --- a/spa/plugins/alsa/alsa-seq.c +++ b/spa/plugins/alsa/alsa-seq.c @@ -250,7 +250,9 @@ int spa_alsa_seq_open(struct seq_state *state) snd_seq_port_subscribe_t *sub; snd_seq_addr_t addr; snd_seq_queue_timer_t *timer; + snd_seq_client_pool_t *pool; struct seq_conn reserve[16]; + size_t pool_size; if (state->opened) return 0; @@ -319,6 +321,31 @@ int spa_alsa_seq_open(struct seq_state *state) spa_log_warn(state->log, "failed to set queue timer: %s", snd_strerror(res)); } + /* Increase client pool sizes. This determines the max sysex message that + * can be received. */ + snd_seq_client_pool_alloca(&pool); + if ((res = snd_seq_get_client_pool(state->event.hndl, pool)) < 0) { + spa_log_warn(state->log, "failed to get pool: %s", snd_strerror(res)); + } else { + /* make sure we at least use the default size */ + pool_size = snd_seq_client_pool_get_output_pool(pool); + pool_size = SPA_MAX(pool_size, snd_seq_client_pool_get_input_pool(pool)); + + /* The pool size is in cells, which are about 24 bytes long. Try to + * make sure we can fit sysex of at least twice the quantum limit. */ + pool_size = SPA_MAX(pool_size, state->quantum_limit * 2 / 24); + /* The kernel ignores values larger than 2000 (by default) so clamp + * this here. It's configurable in case the kernel was modified. */ + pool_size = SPA_CLAMP(pool_size, state->min_pool_size, state->max_pool_size); + + snd_seq_client_pool_set_input_pool(pool, pool_size); + snd_seq_client_pool_set_output_pool(pool, pool_size); + + if ((res = snd_seq_set_client_pool(state->event.hndl, pool)) < 0) { + spa_log_warn(state->log, "failed to set pool: %s", snd_strerror(res)); + } + } + init_ports(state); if ((res = spa_system_timerfd_create(state->data_system, diff --git a/spa/plugins/alsa/alsa-seq.h b/spa/plugins/alsa/alsa-seq.h index d44ad6258..23f71d639 100644 --- a/spa/plugins/alsa/alsa-seq.h +++ b/spa/plugins/alsa/alsa-seq.h @@ -35,7 +35,7 @@ struct props { bool disable_longname; }; -#define MAX_EVENT_SIZE 1024 +#define MAX_EVENT_SIZE 256 #define MAX_PORTS 256 #define MAX_BUFFERS 32 @@ -132,6 +132,8 @@ struct seq_state { struct spa_io_position *position; uint32_t quantum_limit; + uint32_t min_pool_size; + uint32_t max_pool_size; int rate_denom; uint32_t duration;