📄 af_ladspa.c
字号:
char *buf; const char *end, *start, *ladspapath; int endsinso, needslash; size_t filenamelen; void *result = NULL;# ifdef WIN32 /* for windows there's only absolute path support. * if you have a windows machine, feel free to fix * this. (path separator, shared objects extension, * et cetera). */ af_msg(AF_MSG_VERBOSE, "\ton windows, only absolute pathnames " "are supported\n"); af_msg(AF_MSG_VERBOSE, "\ttrying %s\n", filename); return dlopen(filename, flag);# endif filenamelen = strlen(filename); endsinso = 0; if (filenamelen > 3) endsinso = (strcmp(filename+filenamelen-3, ".so") == 0); if (!endsinso) { buf=malloc(filenamelen+4); strcpy(buf, filename); strcat(buf, ".so"); result=mydlopen(buf, flag); free(buf); } if (result) return result; ladspapath=getenv("LADSPA_PATH"); if (ladspapath) { start=ladspapath; while (*start != '\0') { end=start; while ( (*end != ':') && (*end != '\0') ) end++; buf=malloc(filenamelen + 2 + (end-start) ); if (end > start) strncpy(buf, start, end-start); needslash=0; if (end > start) if (*(end-1) != '/') { needslash = 1; buf[end-start] = '/'; } strcpy(buf+needslash+(end-start), filename); af_msg(AF_MSG_VERBOSE, "\ttrying %s\n", buf); result=dlopen(buf, flag); free(buf); if (result) return result; start = end; if (*start == ':') start++; } /* end while there's still more in the path */ } /* end if there's a ladspapath */ /* last resort, just open it again, so the dlerror() message is correct */ af_msg(AF_MSG_VERBOSE, "\ttrying %s\n", filename); return dlopen(filename,flag);}/* ------------------------------------------------------------------------- *//** \brief Load a LADSPA Plugin * * This function loads the LADSPA plugin specified by the file and label * that are present in the setup variable. First, it loads the library. * If it fails, it returns AF_ERROR. If not, it continues to look for the * specified label. If it finds it, it sets the plugin_descriptor inside * setup and returns AF_OK. If it doesn't, it returns AF_ERROR. Special case * is a label called 'help'. In that case, it prints a list of all available * labels (filters) in the library specified by file. * * \param setup Current setup of the filter. Contains filename and label. * * \return Either AF_ERROR or AF_OK, depending on the success of the operation. */static int af_ladspa_load_plugin(af_ladspa_t *setup) { const LADSPA_Descriptor *ladspa_descriptor; LADSPA_Descriptor_Function descriptor_function; int i; /* load library */ af_msg(AF_MSG_VERBOSE, "%s: loading ladspa plugin library %s\n", setup->myname, setup->file); setup->libhandle = mydlopen(setup->file, RTLD_NOW); if (!setup->libhandle) { af_msg(AF_MSG_ERROR, "%s: %s %s\n\t%s\n", setup->myname, MSGTR_AF_LADSPA_ErrFailedToLoad, setup->file, dlerror() ); return AF_ERROR; } af_msg(AF_MSG_VERBOSE, "%s: library found.\n", setup->myname); /* find descriptor function */ dlerror(); descriptor_function = (LADSPA_Descriptor_Function) dlsym (setup->libhandle, "ladspa_descriptor"); if (!descriptor_function) { af_msg(AF_MSG_ERROR, "%s: %s\n\t%s\n", setup->myname, MSGTR_AF_LADSPA_ErrNoDescriptor, dlerror()); return AF_ERROR; } /* if label == help, list all labels in library and exit */ if (strcmp(setup->label, "help") == 0) { af_msg(AF_MSG_INFO, "%s: %s %s:\n", setup->myname, MSGTR_AF_LADSPA_AvailableLabels, setup->file); for (i=0; ; i++) { ladspa_descriptor = descriptor_function(i); if (ladspa_descriptor == NULL) { return AF_ERROR; } af_msg(AF_MSG_INFO, " %-16s - %s (%lu)\n", ladspa_descriptor->Label, ladspa_descriptor->Name, ladspa_descriptor->UniqueID); } } af_msg(AF_MSG_VERBOSE, "%s: looking for label\n", setup->myname); /* find label in library */ for (i=0; ; i++) { ladspa_descriptor = descriptor_function(i); if (ladspa_descriptor == NULL) { af_msg(AF_MSG_ERROR, "%s: %s\n", setup->myname, MSGTR_AF_LADSPA_ErrLabelNotFound); return AF_ERROR; } if (strcmp(ladspa_descriptor->Label, setup->label) == 0) { setup->plugin_descriptor = ladspa_descriptor; af_msg(AF_MSG_VERBOSE, "%s: %s found\n", setup->myname, setup->label); return AF_OK; } } return AF_OK;}/* ------------------------------------------------------------------------- *//** \brief Print a malloc() failed error message. * * Generic function which can be called if a call to malloc(), calloc(), * strdup(), et cetera, failed. It prints a message to the console and * returns AF_ERROR. * * \return AF_ERROR */static int af_ladspa_malloc_failed(char *myname) { af_msg(AF_MSG_ERROR, "%s: %s\n", myname, MSGTR_MemAllocFailed); return AF_ERROR;}/* ------------------------------------------------------------------------- *//** \brief Controls the filter. * * Control the behaviour of the filter. * * Commands: * CONTROL_REINIT Sets the af structure with proper values for number * of channels, rate, format, et cetera. * CONTROL_COMMAND_LINE Parses the suboptions given to this filter * through arg. It first parses the filename and * the label. After that, it loads the filter * and finds out its proprties. Then in continues * parsing the controls given on the commandline, * if any are needed. * * \param af Audio filter instance * \param cmd The command to execute * \param arg Arguments to the command * * \return Either AF_ERROR or AF_OK, depending on the succes of the * operation. */static int control(struct af_instance_s *af, int cmd, void *arg) { af_ladspa_t *setup = (af_ladspa_t*) af->setup; int i, r; float val; switch(cmd) { case AF_CONTROL_REINIT: mp_msg(MSGT_AFILTER, MSGL_V, "%s: (re)init\n", setup->myname); if (!arg) return AF_ERROR; /* for now, only accept 16 bit signed int */ af->data->rate = ((af_data_t*)arg)->rate; af->data->nch = ((af_data_t*)arg)->nch; af->data->format = AF_FORMAT_S16_NE; af->data->bps = 2; /* arg->len is not set here yet, so init of buffers and connecting the * filter, has to be done in play() :-/ */ return af_test_output(af, (af_data_t*)arg); case AF_CONTROL_COMMAND_LINE: { char *buf; mp_msg(MSGT_AFILTER, MSGL_V, "%s: parse suboptions\n", setup->myname); /* suboption parser here! * format is (ladspa=)file:label:controls.... */ if (!arg) { af_msg(AF_MSG_ERROR, "%s: %s\n", setup->myname, MSGTR_AF_LADSPA_ErrNoSuboptions); return AF_ERROR; } buf = malloc(strlen(arg)+1); if (!buf) return af_ladspa_malloc_failed(setup->myname); /* file... */ buf[0] = '\0'; sscanf(arg, "%[^:]", buf); if (buf[0] == '\0') { af_msg(AF_MSG_ERROR, "%s: %s\n", setup->myname, MSGTR_AF_LADSPA_ErrNoLibFile); free(buf); return AF_ERROR; } arg += strlen(buf); setup->file = strdup(buf); if (!setup->file) return af_ladspa_malloc_failed(setup->myname); af_msg(AF_MSG_VERBOSE, "%s: file --> %s\n", setup->myname, setup->file); if (*(char*)arg != '\0') arg++; /* read ':' */ /* label... */ buf[0] = '\0'; sscanf(arg, "%[^:]", buf); if (buf[0] == '\0') { af_msg(AF_MSG_ERROR, "%s: %s\n", setup->myname, MSGTR_AF_LADSPA_ErrNoLabel); free(buf); return AF_ERROR; } arg += strlen(buf); setup->label = strdup(buf); if (!setup->label) return af_ladspa_malloc_failed(setup->myname); af_msg(AF_MSG_VERBOSE, "%s: label --> %s\n", setup->myname, setup->label);/* if (*(char*)arg != '0') arg++; */ /* read ':' */ free(buf); /* no longer needed */ /* set new setup->myname */ if(setup->myname) free(setup->myname); setup->myname = calloc(strlen(af_info_ladspa.name)+strlen(setup->file)+ strlen(setup->label)+6, 1); snprintf(setup->myname, strlen(af_info_ladspa.name)+ strlen(setup->file)+strlen(setup->label)+6, "%s: (%s:%s)", af_info_ladspa.name, setup->file, setup->label); /* load plugin :) */ if ( af_ladspa_load_plugin(setup) != AF_OK ) return AF_ERROR; /* see what inputs, outputs and controls this plugin has */ if ( af_ladspa_parse_plugin(setup) != AF_OK ) return AF_ERROR; /* ninputcontrols is set by now, read control values from arg */ for(i=0; i<setup->ninputcontrols; i++) { if (!arg || (*(char*)arg != ':') ) { af_msg(AF_MSG_ERROR, "%s: %s\n", setup->myname, MSGTR_AF_LADSPA_ErrNotEnoughControls); return AF_ERROR; } arg++; r = sscanf(arg, "%f", &val); if (r!=1) { af_msg(AF_MSG_ERROR, "%s: %s\n", setup->myname, MSGTR_AF_LADSPA_ErrNotEnoughControls); return AF_ERROR; } setup->inputcontrols[setup->inputcontrolsmap[i]] = val; arg = strchr(arg, ':'); } af_msg(AF_MSG_VERBOSE, "%s: input controls: ", setup->myname); for(i=0; i<setup->ninputcontrols; i++) { af_msg(AF_MSG_VERBOSE, "%0.4f ", setup->inputcontrols[setup->inputcontrolsmap[i]]); } af_msg(AF_MSG_VERBOSE, "\n"); /* check boundaries of inputcontrols */ af_msg(AF_MSG_VERBOSE, "%s: checking boundaries of input controls\n", setup->myname); for(i=0; i<setup->ninputcontrols; i++) { int p = setup->inputcontrolsmap[i]; LADSPA_PortRangeHint hint = setup->plugin_descriptor->PortRangeHints[p]; val = setup->inputcontrols[p]; if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) && val < hint.LowerBound) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -