mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	Manage dlobj lifetime in pcm_hooks.c
The shared object may be still needed depending on the implementation of hook-installation functions. When any hooks are registered in the installation function, the dlobj has to be kept opened until closing the PCM instance. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
							parent
							
								
									608cccb088
								
							
						
					
					
						commit
						2a77d217a6
					
				
					 1 changed files with 53 additions and 12 deletions
				
			
		| 
						 | 
					@ -43,12 +43,39 @@ struct _snd_pcm_hook {
 | 
				
			||||||
	struct list_head list;
 | 
						struct list_head list;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct snd_pcm_hook_dllist {
 | 
				
			||||||
 | 
						void *dlobj;
 | 
				
			||||||
 | 
						struct list_head list;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
	snd_pcm_generic_t gen;
 | 
						snd_pcm_generic_t gen;
 | 
				
			||||||
	struct list_head hooks[SND_PCM_HOOK_TYPE_LAST + 1];
 | 
						struct list_head hooks[SND_PCM_HOOK_TYPE_LAST + 1];
 | 
				
			||||||
 | 
						struct list_head dllist;
 | 
				
			||||||
} snd_pcm_hooks_t;
 | 
					} snd_pcm_hooks_t;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int hook_add_dlobj(snd_pcm_t *pcm, void *dlobj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						snd_pcm_hooks_t *h = pcm->private_data;
 | 
				
			||||||
 | 
						struct snd_pcm_hook_dllist *dl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dl = malloc(sizeof(*dl));
 | 
				
			||||||
 | 
						if (!dl)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dl->dlobj = dlobj;
 | 
				
			||||||
 | 
						list_add_tail(&dl->list, &h->dllist);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void hook_remove_dlobj(struct snd_pcm_hook_dllist *dl)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						list_del(&dl->list);
 | 
				
			||||||
 | 
						snd_dlclose(dl->dlobj);
 | 
				
			||||||
 | 
						free(dl);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int snd_pcm_hooks_close(snd_pcm_t *pcm)
 | 
					static int snd_pcm_hooks_close(snd_pcm_t *pcm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	snd_pcm_hooks_t *h = pcm->private_data;
 | 
						snd_pcm_hooks_t *h = pcm->private_data;
 | 
				
			||||||
| 
						 | 
					@ -71,6 +98,11 @@ static int snd_pcm_hooks_close(snd_pcm_t *pcm)
 | 
				
			||||||
			snd_pcm_hook_remove(hook);
 | 
								snd_pcm_hook_remove(hook);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						while (!list_empty(&h->dllist)) {
 | 
				
			||||||
 | 
							struct snd_pcm_hook_dllist *dl;
 | 
				
			||||||
 | 
							pos = h->dllist.next;
 | 
				
			||||||
 | 
							hook_remove_dlobj(list_entry(pos, struct snd_pcm_hook_dllist, list));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	err = snd_pcm_generic_close(pcm);
 | 
						err = snd_pcm_generic_close(pcm);
 | 
				
			||||||
	if (err < 0)
 | 
						if (err < 0)
 | 
				
			||||||
		res = err;
 | 
							res = err;
 | 
				
			||||||
| 
						 | 
					@ -193,6 +225,7 @@ int snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int
 | 
				
			||||||
	for (k = 0; k <= SND_PCM_HOOK_TYPE_LAST; ++k) {
 | 
						for (k = 0; k <= SND_PCM_HOOK_TYPE_LAST; ++k) {
 | 
				
			||||||
		INIT_LIST_HEAD(&h->hooks[k]);
 | 
							INIT_LIST_HEAD(&h->hooks[k]);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&h->dllist);
 | 
				
			||||||
	err = snd_pcm_new(&pcm, SND_PCM_TYPE_HOOKS, name, slave->stream, slave->mode);
 | 
						err = snd_pcm_new(&pcm, SND_PCM_TYPE_HOOKS, name, slave->stream, slave->mode);
 | 
				
			||||||
	if (err < 0) {
 | 
						if (err < 0) {
 | 
				
			||||||
		free(h);
 | 
							free(h);
 | 
				
			||||||
| 
						 | 
					@ -312,6 +345,8 @@ static int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *root, snd_config_
 | 
				
			||||||
	snd_config_iterator_t i, next;
 | 
						snd_config_iterator_t i, next;
 | 
				
			||||||
	int (*install_func)(snd_pcm_t *pcm, snd_config_t *args) = NULL;
 | 
						int (*install_func)(snd_pcm_t *pcm, snd_config_t *args) = NULL;
 | 
				
			||||||
	void *h = NULL;
 | 
						void *h = NULL;
 | 
				
			||||||
 | 
						struct snd_pcm_hook_dllist *dl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND) {
 | 
						if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND) {
 | 
				
			||||||
		SNDERR("Invalid hook definition");
 | 
							SNDERR("Invalid hook definition");
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -402,7 +437,9 @@ static int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *root, snd_config_
 | 
				
			||||||
       _err:
 | 
					       _err:
 | 
				
			||||||
	if (type)
 | 
						if (type)
 | 
				
			||||||
		snd_config_delete(type);
 | 
							snd_config_delete(type);
 | 
				
			||||||
	if (err >= 0) {
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (args && snd_config_get_string(args, &str) >= 0) {
 | 
						if (args && snd_config_get_string(args, &str) >= 0) {
 | 
				
			||||||
		err = snd_config_search_definition(root, "hook_args", str, &args);
 | 
							err = snd_config_search_definition(root, "hook_args", str, &args);
 | 
				
			||||||
		if (err < 0)
 | 
							if (err < 0)
 | 
				
			||||||
| 
						 | 
					@ -412,10 +449,14 @@ static int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *root, snd_config_
 | 
				
			||||||
		snd_config_delete(args);
 | 
							snd_config_delete(args);
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		err = install_func(pcm, args);
 | 
							err = install_func(pcm, args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (err >= 0)
 | 
				
			||||||
 | 
							err = hook_add_dlobj(pcm, h);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (err < 0) {
 | 
				
			||||||
		snd_dlclose(h);
 | 
							snd_dlclose(h);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (err < 0)
 | 
					 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue