⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 plugin.c

📁 Aqualung is an advanced music player primarily targeted for the GNU/Linux operating system, but als
💻 C
📖 第 1 页 / 共 5 页
字号:
/*                                                     -*- linux-c -*-    Copyright (C) 2004 Tom Szilagyi    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    $Id: plugin.c,v 1.26 2006/09/12 17:52:05 peterszilagyi Exp $*/#include <config.h>#ifdef HAVE_LADSPA#include <stdio.h>#include <stdlib.h>#include <dlfcn.h>#include <unistd.h>#include <dirent.h>#include <lrdf.h>#include <libxml/xmlmemory.h>#include <libxml/parser.h>#include <gtk/gtk.h>#include <gdk/gdkkeysyms.h>#include "common.h"#include "i18n.h"#include "options.h"#include "trashlist.h"#include "plugin.h"#ifdef __FreeBSD__#define dirent64 dirent#define scandir64 scandir#define alphasort64 alphasort#endif /* __FreeBSD__ */extern options_t options;extern GtkWidget* gui_stock_label_button(gchar *blabel, const gchar *bstock);extern volatile int plugin_lock;extern int n_plugins;extern plugin_instance * plugin_vect[MAX_PLUGINS];extern unsigned long ladspa_buflen;extern LADSPA_Data * l_buf;extern LADSPA_Data * r_buf;extern unsigned long out_SR;int fxbuilder_on;GtkWidget * fxbuilder_window;GtkWidget * avail_list;GtkListStore * avail_store = NULL;GtkTreeSelection * avail_select;GtkWidget * running_list;GtkListStore * running_store = NULL;GtkTreeSelection * running_select;GtkWidget * add_button;GtkWidget * remove_button;GtkWidget * conf_button;GtkWidget * rp_menu;GtkWidget * scrolled_win_running;extern GtkWidget * plugin_toggle;typedef struct {	plugin_instance * instance;	int index;} optdata_t;typedef struct {	plugin_instance * instance;	float start;} btnpdata_t;int added_plugin = 0;voidset_active_state(void) {		GtkTreeIter iter;        if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(running_store), &iter, NULL, 0)) {                /* disable buttons and menu */                gtk_widget_set_sensitive(remove_button, FALSE);                gtk_widget_set_sensitive(conf_button, FALSE);        } else {                /* enable buttons and menu */                gtk_widget_set_sensitive(remove_button, TRUE);                gtk_widget_set_sensitive(conf_button, TRUE);        }}static intrdf_filter(const struct dirent64 * de) {	if (de->d_type != DT_UNKNOWN && de->d_type != DT_REG && de->d_type != DT_LNK)		return 0;	if (de->d_name[0] == '.')		return 0;	return (((strlen(de->d_name) >= 4) && (strcmp(de->d_name + strlen(de->d_name) - 3, ".n3") == 0)) ||		((strlen(de->d_name) >= 5) && (strcmp(de->d_name + strlen(de->d_name) - 4, ".rdf") == 0)) ||		((strlen(de->d_name) >= 6) && (strcmp(de->d_name + strlen(de->d_name) - 5, ".rdfs") == 0)));}static intso_filter(const struct dirent64 * de) {	if (de->d_type != DT_UNKNOWN && de->d_type != DT_REG && de->d_type != DT_LNK)		return 0;	if (de->d_name[0] == '.')		return 0;	return ((strlen(de->d_name) >= 4) && (strcmp(de->d_name + strlen(de->d_name) - 3, ".so") == 0));}voidparse_lrdf_data(void) {	char * str;	char lrdf_path[MAXLEN];	char rdf_path[MAXLEN];	char fileuri[MAXLEN];	int i, j = 0;	struct dirent64 ** de;	int n;	lrdf_path[0] = '\0';	if ((str = getenv("LADSPA_RDF_PATH"))) {		snprintf(lrdf_path, MAXLEN-1, "%s:", str);	} else {                strncat(lrdf_path, "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf:", MAXLEN-1);	}	for (i = 0; lrdf_path[i] != '\0'; i++) {		if (lrdf_path[i] == ':') {			rdf_path[j] = '\0';			j = 0;			n = scandir64(rdf_path, &de, rdf_filter, alphasort64);			if (n >= 0) {				int c;								for (c = 0; c < n; ++c) {					snprintf(fileuri, MAXLEN-1, "file://%s/%s", rdf_path, de[c]->d_name);					if (lrdf_read_file(fileuri)) {						fprintf(stderr,							"warning: could not parse RDF file: %s\n", fileuri);					}				}			}		} else {			rdf_path[j++] = lrdf_path[i];		}	}}voidget_ladspa_category(unsigned long plugin_id, char * str) {        char buf[256];        lrdf_statement pattern;	lrdf_statement * matches1;	lrdf_statement * matches2;        snprintf(buf, 255, "%s%lu", LADSPA_BASE, plugin_id);        pattern.subject = buf;        pattern.predicate = RDF_TYPE;        pattern.object = 0;        pattern.object_type = lrdf_uri;        matches1 = lrdf_matches(&pattern);        if (!matches1) {                strncpy(str, "Unknown", MAXLEN-1);		return;        }        pattern.subject = matches1->object;        pattern.predicate = LADSPA_BASE "hasLabel";        pattern.object = 0;        pattern.object_type = lrdf_literal;        matches2 = lrdf_matches (&pattern);        lrdf_free_statements(matches1);        if (!matches2) {                strncpy(str, "Unknown", MAXLEN-1);                return;        }        strncpy(str, matches2->object, MAXLEN-1);        lrdf_free_statements(matches2);}static voidfind_plugins(char * path_entry) {	void * library = NULL;	char lib_name[MAXLEN];	LADSPA_Descriptor_Function descriptor_fn;	const LADSPA_Descriptor * descriptor;	struct dirent64 ** de;	int n, k, c;	long int port, n_ins, n_outs;	GtkTreeIter iter;	char id_str[32];	char n_ins_str[32];	char n_outs_str[32];	char c_str[32];	char category[MAXLEN];	n = scandir64(path_entry, &de, so_filter, alphasort64);	if (n >= 0) {		for (c = 0; c < n; ++c) {			snprintf(lib_name, MAXLEN-1, "%s/%s", path_entry, de[c]->d_name);			library = dlopen(lib_name, RTLD_LAZY);			if (library == NULL) {				continue;			}			descriptor_fn = dlsym(library, "ladspa_descriptor");			if (descriptor_fn == NULL) {				dlclose(library);				continue;			}			for (k = 0; ; ++k) {				descriptor = descriptor_fn(k);				if (descriptor == NULL) {					break;				}				for (n_ins = n_outs = port = 0; port < descriptor->PortCount; ++port) {					if (LADSPA_IS_PORT_AUDIO(descriptor->PortDescriptors[port])) {						if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[port]))							++n_ins;						if (LADSPA_IS_PORT_OUTPUT(descriptor->PortDescriptors[port]))							++n_outs;					}				}				if ((n_ins == 1 && n_outs == 1) || (n_ins == 2 && n_outs == 2)) {										get_ladspa_category(descriptor->UniqueID, category);					snprintf(id_str, 31, "%ld", descriptor->UniqueID);					snprintf(n_ins_str, 31, "%ld", n_ins);					snprintf(n_outs_str, 31, "%ld", n_outs);					snprintf(c_str, 31, "%d", k);										gtk_list_store_append(avail_store, &iter);					gtk_list_store_set(avail_store, &iter, 0, id_str,							   1, descriptor->Name, 2, category,							   3, n_ins_str, 4, n_outs_str,							   5, lib_name, 6, c_str, -1);				}			}			dlclose(library);		}	}}static voidfind_all_plugins(void) {	char * ladspa_path;	char * directory;	if (!(ladspa_path = getenv("LADSPA_PATH"))) {		find_plugins("/usr/lib/ladspa");		find_plugins("/usr/local/lib/ladspa");	} else {		ladspa_path = strdup(ladspa_path);		directory = strtok(ladspa_path, ":");		while (directory != NULL) {			find_plugins(directory);			directory = strtok(NULL, ":");		}		free(ladspa_path);	}}static gbooleanfxbuilder_close(GtkWidget * widget, GdkEvent * event, gpointer data) {        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(plugin_toggle), FALSE);        return TRUE;}voidshow_fxbuilder(void) {        set_active_state();	gtk_widget_show_all(fxbuilder_window);	fxbuilder_on = 1;}voidhide_fxbuilder(void) {	gtk_widget_hide(fxbuilder_window);	fxbuilder_on = 0;}gintfxbuilder_key_pressed(GtkWidget * widget, GdkEventKey * event, gpointer * data) {        switch (event->keyval) {	case GDK_q:	case GDK_Q:	case GDK_Escape:		fxbuilder_close(NULL, NULL, NULL);		return TRUE;	};	return FALSE;}/* we need this because the default gtk sort func doesn't obey spaces in strings   eg. "ABCE" gets in between "ABC D" and "ABC F" and not after them.*/gintcompare_func(GtkTreeModel * model, GtkTreeIter * a, GtkTreeIter * b, gpointer user_data) {	int col = (int) user_data;	char * sa;	char * sb;	int ret;	gtk_tree_model_get(model, a, col, &sa, -1);	gtk_tree_model_get(model, b, col, &sb, -1);	ret = strcmp(sa, sb);	g_free(sa);	g_free(sb);	return ret;}plugin_instance *instantiate(char * filename, int index) {	LADSPA_Descriptor_Function descriptor_fn;	plugin_instance * instance;	int n_ins, n_outs, n_ctrl, port;	if ((instance = calloc(1, sizeof(plugin_instance))) == NULL) {		fprintf(stderr, "plugin.c: instantiate(): calloc error\n");		return NULL;	}	strncpy(instance->filename, filename, MAXLEN-1);	instance->index = index;	instance->library = dlopen(filename, RTLD_NOW);	if (instance->library == NULL) {		fprintf(stderr, "dlopen() failed on %s -- is it a valid shared library file?\n", filename);		free(instance);		return NULL;	}	descriptor_fn = dlsym(instance->library, "ladspa_descriptor");	if (descriptor_fn == NULL) {		fprintf(stderr,			"dlsym() failed to load symbol 'ladspa_descriptor'. "			"Possibly a bug in %s\n", filename);		dlclose(instance->library);		free(instance);		return NULL;	}	instance->descriptor = descriptor_fn(index);	if (LADSPA_IS_INPLACE_BROKEN(instance->descriptor->Properties)) {		fprintf(stderr,			"%s (%s) is INPLACE_BROKEN and thus unusable in "			"Aqualung at this time.\n", instance->descriptor->Label, instance->descriptor->Name);		dlclose(instance->library);		free(instance);		return NULL;	}	for (n_ins = n_outs = n_ctrl = port = 0; port < instance->descriptor->PortCount; ++port) {		if (LADSPA_IS_PORT_AUDIO(instance->descriptor->PortDescriptors[port])) {			if (LADSPA_IS_PORT_INPUT(instance->descriptor->PortDescriptors[port]))				++n_ins;			if (LADSPA_IS_PORT_OUTPUT(instance->descriptor->PortDescriptors[port]))				++n_outs;		} else {			++n_ctrl;		}	}	if (n_ctrl > MAX_KNOBS) {                fprintf(stderr,			"%s (%s) has more than %d input knobs; "			"Aqualung cannot use it.\n",			instance->descriptor->Label, instance->descriptor->Name, MAX_KNOBS);                dlclose(instance->library);                free(instance);                return NULL;	}	if ((n_ins == 1) && (n_outs == 1)) {		instance->is_mono = 1;		instance->handle = instance->descriptor->instantiate(instance->descriptor, out_SR);		instance->handle2 = instance->descriptor->instantiate(instance->descriptor, out_SR);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -