mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	pcm_ladspa - setup control outputs all times
It turned out that plugins that had control outputs were not being set up properly if there was no corresponding "output" section. Signed-off-by: Nathan Kurz <nate@verse.com>
This commit is contained in:
		
							parent
							
								
									9a8a3374a1
								
							
						
					
					
						commit
						d9cfe1e9ff
					
				
					 1 changed files with 170 additions and 121 deletions
				
			
		| 
						 | 
				
			
			@ -1211,6 +1211,152 @@ static int snd_pcm_ladspa_look_for_plugin(snd_pcm_ladspa_plugin_t * const plugin
 | 
			
		|||
	return -ENOENT;
 | 
			
		||||
}					  
 | 
			
		||||
 | 
			
		||||
static int snd_pcm_ladspa_add_default_controls(snd_pcm_ladspa_plugin_t *lplug,
 | 
			
		||||
					       snd_pcm_ladspa_plugin_io_t *io) 
 | 
			
		||||
{
 | 
			
		||||
	unsigned int count = 0;
 | 
			
		||||
	LADSPA_Data *array;
 | 
			
		||||
	unsigned char *initialized;
 | 
			
		||||
	unsigned long idx;
 | 
			
		||||
 | 
			
		||||
	for (idx = 0; idx < lplug->desc->PortCount; idx++)
 | 
			
		||||
		if ((lplug->desc->PortDescriptors[idx] & (io->pdesc | LADSPA_PORT_CONTROL)) == (io->pdesc | LADSPA_PORT_CONTROL))
 | 
			
		||||
			count++;
 | 
			
		||||
	array = (LADSPA_Data *)calloc(count, sizeof(LADSPA_Data));
 | 
			
		||||
	if (!array)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	initialized = (unsigned char *)calloc(count, sizeof(unsigned char));
 | 
			
		||||
	if (!initialized) {
 | 
			
		||||
		free(array);
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	}
 | 
			
		||||
	io->controls_size = count;
 | 
			
		||||
	io->controls_initialized = initialized;
 | 
			
		||||
	io->controls = array;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}	
 | 
			
		||||
 | 
			
		||||
static int snd_pcm_ladspa_parse_controls(snd_pcm_ladspa_plugin_t *lplug,
 | 
			
		||||
					 snd_pcm_ladspa_plugin_io_t *io,
 | 
			
		||||
					 snd_config_t *controls) 
 | 
			
		||||
{
 | 
			
		||||
	snd_config_iterator_t i, next;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if (snd_config_get_type(controls) != SND_CONFIG_TYPE_COMPOUND) {
 | 
			
		||||
		SNDERR("controls definition must be a compound");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	snd_config_for_each(i, next, controls) {
 | 
			
		||||
		snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
		const char *id;
 | 
			
		||||
		long lval;
 | 
			
		||||
		unsigned int port, uval;
 | 
			
		||||
		double dval;
 | 
			
		||||
		if (snd_config_get_id(n, &id) < 0)
 | 
			
		||||
			continue;
 | 
			
		||||
		err = safe_strtol(id, &lval);
 | 
			
		||||
		if (err >= 0) {
 | 
			
		||||
			err = snd_pcm_ladspa_find_port(&port, lplug, io->pdesc | LADSPA_PORT_CONTROL, lval);
 | 
			
		||||
		} else {
 | 
			
		||||
			err = snd_pcm_ladspa_find_sport(&port, lplug, io->pdesc | LADSPA_PORT_CONTROL, id);
 | 
			
		||||
		}
 | 
			
		||||
		if (err < 0) {
 | 
			
		||||
			SNDERR("Unable to find an control port (%s)", id);
 | 
			
		||||
			return err;
 | 
			
		||||
		}
 | 
			
		||||
		if (snd_config_get_ireal(n, &dval) < 0) {
 | 
			
		||||
			SNDERR("Control port %s has not an float or integer value", id);
 | 
			
		||||
			return err;
 | 
			
		||||
		}
 | 
			
		||||
		err = snd_pcm_ladspa_find_port_idx(&uval, lplug, io->pdesc | LADSPA_PORT_CONTROL, port);
 | 
			
		||||
		if (err < 0) {
 | 
			
		||||
			SNDERR("internal error");
 | 
			
		||||
			return err;
 | 
			
		||||
		}
 | 
			
		||||
		io->controls_initialized[uval] = 1;
 | 
			
		||||
		io->controls[uval] = (LADSPA_Data)dval;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int snd_pcm_ladspa_parse_bindings(snd_pcm_ladspa_plugin_t *lplug,
 | 
			
		||||
					 snd_pcm_ladspa_plugin_io_t *io,
 | 
			
		||||
					 snd_config_t *bindings) 
 | 
			
		||||
{
 | 
			
		||||
	unsigned int count = 0;
 | 
			
		||||
	unsigned int *array;
 | 
			
		||||
	snd_config_iterator_t i, next;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if (snd_config_get_type(bindings) != SND_CONFIG_TYPE_COMPOUND) {
 | 
			
		||||
		SNDERR("bindings definition must be a compound");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	snd_config_for_each(i, next, bindings) {
 | 
			
		||||
		snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
		const char *id;
 | 
			
		||||
		long channel;
 | 
			
		||||
		if (snd_config_get_id(n, &id) < 0)
 | 
			
		||||
			continue;
 | 
			
		||||
		err = safe_strtol(id, &channel);
 | 
			
		||||
		if (err < 0 || channel < 0) {
 | 
			
		||||
			SNDERR("Invalid channel number: %s", id);
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		if (lplug->policy == SND_PCM_LADSPA_POLICY_DUPLICATE && channel > 0) {
 | 
			
		||||
			SNDERR("Wrong channel specification for duplicate policy");
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		if (count < (unsigned int)(channel + 1))
 | 
			
		||||
			count = (unsigned int)(channel + 1);
 | 
			
		||||
	}
 | 
			
		||||
	if (count > 0) {
 | 
			
		||||
		array = (unsigned int *)calloc(count, sizeof(unsigned int));
 | 
			
		||||
		if (! array)
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
		memset(array, 0xff, count * sizeof(unsigned int));
 | 
			
		||||
		io->port_bindings_size = count;
 | 
			
		||||
		io->port_bindings = array;
 | 
			
		||||
		snd_config_for_each(i, next, bindings) {
 | 
			
		||||
			snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
			const char *id, *sport;
 | 
			
		||||
			long channel, port;
 | 
			
		||||
			if (snd_config_get_id(n, &id) < 0)
 | 
			
		||||
				continue;
 | 
			
		||||
			err = safe_strtol(id, &channel);
 | 
			
		||||
			if (err < 0 || channel < 0) {
 | 
			
		||||
				assert(0);	/* should never happen */
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
			}
 | 
			
		||||
			err = snd_config_get_integer(n, &port);
 | 
			
		||||
			if (err >= 0) {
 | 
			
		||||
				err = snd_pcm_ladspa_find_port(&array[channel], lplug, io->pdesc | LADSPA_PORT_AUDIO, port);
 | 
			
		||||
				if (err < 0) {
 | 
			
		||||
					SNDERR("Unable to find an audio port (%li) for channel %s", port, id);
 | 
			
		||||
					return err;
 | 
			
		||||
				}
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			err = snd_config_get_string(n, &sport);
 | 
			
		||||
			if (err < 0) {
 | 
			
		||||
				SNDERR("Invalid LADSPA port field type for %s", id);
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
			}
 | 
			
		||||
			err = snd_pcm_ladspa_find_sport(&array[channel], lplug, io->pdesc | LADSPA_PORT_AUDIO, sport);
 | 
			
		||||
			if (err < 0) {
 | 
			
		||||
				SNDERR("Unable to find an audio port (%s) for channel %s", sport, id);
 | 
			
		||||
				return err;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int snd_pcm_ladspa_parse_ioconfig(snd_pcm_ladspa_plugin_t *lplug,
 | 
			
		||||
					 snd_pcm_ladspa_plugin_io_t *io,
 | 
			
		||||
					 snd_config_t *conf)
 | 
			
		||||
| 
						 | 
				
			
			@ -1218,9 +1364,18 @@ static int snd_pcm_ladspa_parse_ioconfig(snd_pcm_ladspa_plugin_t *lplug,
 | 
			
		|||
	snd_config_iterator_t i, next;
 | 
			
		||||
	snd_config_t *bindings = NULL, *controls = NULL;
 | 
			
		||||
	int err;
 | 
			
		||||
	
 | 
			
		||||
	if (conf == NULL)
 | 
			
		||||
 | 
			
		||||
	/* always add default controls for both input and output */
 | 
			
		||||
	err = snd_pcm_ladspa_add_default_controls(lplug, io);
 | 
			
		||||
	if (err < 0) {
 | 
			
		||||
		SNDERR("error adding default controls");
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
	if (conf == NULL) {
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND) {
 | 
			
		||||
		SNDERR("input or output definition must be a compound");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
| 
						 | 
				
			
			@ -1239,127 +1394,21 @@ static int snd_pcm_ladspa_parse_ioconfig(snd_pcm_ladspa_plugin_t *lplug,
 | 
			
		|||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* ignore values of parameters for output controls */
 | 
			
		||||
	if (controls && !(io->pdesc & LADSPA_PORT_OUTPUT)) {
 | 
			
		||||
 		err = snd_pcm_ladspa_parse_controls(lplug, io, controls);
 | 
			
		||||
		if (err < 0) 
 | 
			
		||||
			return err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (bindings) {
 | 
			
		||||
		unsigned int count = 0;
 | 
			
		||||
		unsigned int *array;
 | 
			
		||||
		if (snd_config_get_type(bindings) != SND_CONFIG_TYPE_COMPOUND) {
 | 
			
		||||
			SNDERR("bindings definition must be a compound");
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		snd_config_for_each(i, next, bindings) {
 | 
			
		||||
			snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
			const char *id;
 | 
			
		||||
			long channel;
 | 
			
		||||
			if (snd_config_get_id(n, &id) < 0)
 | 
			
		||||
				continue;
 | 
			
		||||
			err = safe_strtol(id, &channel);
 | 
			
		||||
			if (err < 0 || channel < 0) {
 | 
			
		||||
				SNDERR("Invalid channel number: %s", id);
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
			}
 | 
			
		||||
			if (lplug->policy == SND_PCM_LADSPA_POLICY_DUPLICATE && channel > 0) {
 | 
			
		||||
				SNDERR("Wrong channel specification for duplicate policy");
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
			}
 | 
			
		||||
			if (count < (unsigned int)(channel + 1))
 | 
			
		||||
				count = (unsigned int)(channel + 1);
 | 
			
		||||
		}
 | 
			
		||||
		if (count > 0) {
 | 
			
		||||
			array = (unsigned int *)calloc(count, sizeof(unsigned int));
 | 
			
		||||
			if (! array)
 | 
			
		||||
				return -ENOMEM;
 | 
			
		||||
			memset(array, 0xff, count * sizeof(unsigned int));
 | 
			
		||||
			io->port_bindings_size = count;
 | 
			
		||||
			io->port_bindings = array;
 | 
			
		||||
			snd_config_for_each(i, next, bindings) {
 | 
			
		||||
				snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
				const char *id, *sport;
 | 
			
		||||
				long channel, port;
 | 
			
		||||
				if (snd_config_get_id(n, &id) < 0)
 | 
			
		||||
					continue;
 | 
			
		||||
				err = safe_strtol(id, &channel);
 | 
			
		||||
				if (err < 0 || channel < 0) {
 | 
			
		||||
					assert(0);	/* should never happen */
 | 
			
		||||
					return -EINVAL;
 | 
			
		||||
				}
 | 
			
		||||
				err = snd_config_get_integer(n, &port);
 | 
			
		||||
				if (err >= 0) {
 | 
			
		||||
					err = snd_pcm_ladspa_find_port(&array[channel], lplug, io->pdesc | LADSPA_PORT_AUDIO, port);
 | 
			
		||||
					if (err < 0) {
 | 
			
		||||
						SNDERR("Unable to find an audio port (%li) for channel %s", port, id);
 | 
			
		||||
						return err;
 | 
			
		||||
					}
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				err = snd_config_get_string(n, &sport);
 | 
			
		||||
				if (err < 0) {
 | 
			
		||||
					SNDERR("Invalid LADSPA port field type for %s", id);
 | 
			
		||||
					return -EINVAL;
 | 
			
		||||
				}
 | 
			
		||||
				err = snd_pcm_ladspa_find_sport(&array[channel], lplug, io->pdesc | LADSPA_PORT_AUDIO, sport);
 | 
			
		||||
				if (err < 0) {
 | 
			
		||||
					SNDERR("Unable to find an audio port (%s) for channel %s", sport, id);
 | 
			
		||||
					return err;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (1) {
 | 
			
		||||
		unsigned int count = 0;
 | 
			
		||||
		LADSPA_Data *array;
 | 
			
		||||
		unsigned char *initialized;
 | 
			
		||||
		unsigned long idx;
 | 
			
		||||
		for (idx = 0; idx < lplug->desc->PortCount; idx++)
 | 
			
		||||
			if ((lplug->desc->PortDescriptors[idx] & (io->pdesc | LADSPA_PORT_CONTROL)) == (io->pdesc | LADSPA_PORT_CONTROL))
 | 
			
		||||
				count++;
 | 
			
		||||
		array = (LADSPA_Data *)calloc(count, sizeof(LADSPA_Data));
 | 
			
		||||
		if (!array)
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
		initialized = (unsigned char *)calloc(count, sizeof(unsigned char));
 | 
			
		||||
		if (!initialized) {
 | 
			
		||||
		        free(array);
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
                }
 | 
			
		||||
		io->controls_size = count;
 | 
			
		||||
		io->controls_initialized = initialized;
 | 
			
		||||
		io->controls = array;
 | 
			
		||||
		if (!(io->pdesc & LADSPA_PORT_OUTPUT)) {
 | 
			
		||||
        		if (snd_config_get_type(controls) != SND_CONFIG_TYPE_COMPOUND) {
 | 
			
		||||
        			SNDERR("controls definition must be a compound");
 | 
			
		||||
        			return -EINVAL;
 | 
			
		||||
        		}
 | 
			
		||||
        		snd_config_for_each(i, next, controls) {
 | 
			
		||||
        			snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
        			const char *id;
 | 
			
		||||
        			long lval;
 | 
			
		||||
        			unsigned int port, uval;
 | 
			
		||||
        			double dval;
 | 
			
		||||
        			if (snd_config_get_id(n, &id) < 0)
 | 
			
		||||
        				continue;
 | 
			
		||||
        			err = safe_strtol(id, &lval);
 | 
			
		||||
        			if (err >= 0) {
 | 
			
		||||
        				err = snd_pcm_ladspa_find_port(&port, lplug, io->pdesc | LADSPA_PORT_CONTROL, lval);
 | 
			
		||||
        			} else {
 | 
			
		||||
        				err = snd_pcm_ladspa_find_sport(&port, lplug, io->pdesc | LADSPA_PORT_CONTROL, id);
 | 
			
		||||
        			}
 | 
			
		||||
        			if (err < 0) {
 | 
			
		||||
        				SNDERR("Unable to find an control port (%s)", id);
 | 
			
		||||
        				return err;
 | 
			
		||||
        			}
 | 
			
		||||
        			if (snd_config_get_ireal(n, &dval) < 0) {
 | 
			
		||||
        				SNDERR("Control port %s has not an float or integer value", id);
 | 
			
		||||
        				return err;
 | 
			
		||||
        			}
 | 
			
		||||
        			err = snd_pcm_ladspa_find_port_idx(&uval, lplug, io->pdesc | LADSPA_PORT_CONTROL, port);
 | 
			
		||||
        			if (err < 0) {
 | 
			
		||||
        				SNDERR("internal error");
 | 
			
		||||
        				return err;
 | 
			
		||||
        			}
 | 
			
		||||
        			initialized[uval] = 1;
 | 
			
		||||
        			array[uval] = (LADSPA_Data)dval;
 | 
			
		||||
        		}
 | 
			
		||||
                }
 | 
			
		||||
 		err = snd_pcm_ladspa_parse_bindings(lplug, io, bindings);
 | 
			
		||||
		if (err < 0) 
 | 
			
		||||
			return err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue