Home | History | Annotate | Download | only in simple
      1 /*
      2  *  Mixer Interface - simple abstact module - base library (dlopen function)
      3  *  Copyright (c) 2005 by Jaroslav Kysela <perex (at) perex.cz>
      4  *
      5  *
      6  *   This library is free software; you can redistribute it and/or modify
      7  *   it under the terms of the GNU Lesser General Public License as
      8  *   published by the Free Software Foundation; either version 2.1 of
      9  *   the License, or (at your option) any later version.
     10  *
     11  *   This program is distributed in the hope that it will be useful,
     12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  *   GNU Lesser General Public License for more details.
     15  *
     16  *   You should have received a copy of the GNU Lesser General Public
     17  *   License along with this library; if not, write to the Free Software
     18  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
     19  *
     20  */
     21 
     22 
     23 #include <stdio.h>
     24 #include <stdlib.h>
     25 #include <unistd.h>
     26 #include <string.h>
     27 #include <fcntl.h>
     28 #include <sys/ioctl.h>
     29 #include <math.h>
     30 #include <dlfcn.h>
     31 #include "config.h"
     32 #include "asoundlib.h"
     33 #include "mixer_abst.h"
     34 #include "sbase.h"
     35 
     36 #define SO_PATH ALSA_PLUGIN_DIR "/smixer"
     37 
     38 int mixer_simple_basic_dlopen(snd_mixer_class_t *class,
     39 			      bclass_base_ops_t **ops)
     40 {
     41 	struct bclass_private *priv = snd_mixer_sbasic_get_private(class);
     42 	const char *lib = "smixer-sbase.so";
     43 	void (*initpriv)(snd_mixer_class_t *class, struct bclass_private *priv);
     44 	char *xlib, *path;
     45 	void *h;
     46 	int initflag = 0;
     47 
     48 	if (priv == NULL) {
     49 		priv = calloc(1, sizeof(*priv));
     50 		if (priv == NULL)
     51 			return -ENOMEM;
     52 		initflag = 1;
     53 	}
     54 	path = getenv("ALSA_MIXER_SIMPLE_MODULES");
     55 	if (!path)
     56 		path = SO_PATH;
     57 	xlib = malloc(strlen(lib) + strlen(path) + 1 + 1);
     58 	if (xlib == NULL) {
     59 		if (initflag)
     60 			free(priv);
     61 		return -ENOMEM;
     62 	}
     63 	strcpy(xlib, path);
     64 	strcat(xlib, "/");
     65 	strcat(xlib, lib);
     66 	h = snd_dlopen(xlib, RTLD_NOW);
     67 	if (h == NULL) {
     68 		SNDERR("Unable to open library '%s'", xlib);
     69 		goto __error;
     70 	}
     71 	initpriv = dlsym(h, "alsa_mixer_sbasic_initpriv");
     72 	if (initpriv == NULL) {
     73 		SNDERR("Symbol 'alsa_mixer_sbasic_initpriv' was not found in '%s'", xlib);
     74 		goto __error;
     75 	}
     76 	priv->ops.event = dlsym(h, "alsa_mixer_sbasic_event");
     77 	if (priv->ops.event == NULL) {
     78 		SNDERR("Symbol 'alsa_mixer_sbasic_event' was not found in '%s'", xlib);
     79 		goto __error;
     80 	}
     81 	priv->ops.selreg = dlsym(h, "alsa_mixer_sbasic_selreg");
     82 	if (priv->ops.selreg == NULL) {
     83 		SNDERR("Symbol 'alsa_mixer_sbasic_selreg' was not found in '%s'", xlib);
     84 		goto __error;
     85 	}
     86 	priv->ops.sidreg = dlsym(h, "alsa_mixer_sbasic_sidreg");
     87 	if (priv->ops.sidreg == NULL) {
     88 		SNDERR("Symbol 'alsa_mixer_sbasic_sidreg' was not found in '%s'", xlib);
     89 		goto __error;
     90 	}
     91 	free(xlib);
     92 	if (initflag)
     93 		initpriv(class, priv);
     94 	priv->dl_sbase = h;
     95 	if (ops)
     96 		*ops = &priv->ops;
     97 	return 1;
     98 
     99       __error:
    100       	if (initflag)
    101       		free(priv);
    102 	if (h == NULL)
    103 		snd_dlclose(h);
    104 	free(xlib);
    105 	return -ENXIO;
    106 }
    107