| @@ -1,186 +0,0 @@ | |||
| /* load.c | |||
| Free software by Richard W.E. Furse. Do with as you will. No | |||
| warranty. */ | |||
| /*****************************************************************************/ | |||
| #include <dlfcn.h> | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| /*****************************************************************************/ | |||
| #include "ladspa.h" | |||
| #include "utils.h" | |||
| /*****************************************************************************/ | |||
| /* This function provides a wrapping of dlopen(). When the filename is | |||
| not an absolute path (i.e. does not begin with / character), this | |||
| routine will search the LADSPA_PATH for the file. */ | |||
| static void * | |||
| dlopenLADSPA(const char * pcFilename, int iFlag) { | |||
| char * pcBuffer; | |||
| const char * pcEnd; | |||
| const char * pcLADSPAPath; | |||
| const char * pcStart; | |||
| int iEndsInSO; | |||
| int iNeedSlash; | |||
| size_t iFilenameLength; | |||
| void * pvResult; | |||
| iFilenameLength = strlen(pcFilename); | |||
| pvResult = NULL; | |||
| if (pcFilename[0] == '/') { | |||
| /* The filename is absolute. Assume the user knows what he/she is | |||
| doing and simply dlopen() it. */ | |||
| pvResult = dlopen(pcFilename, iFlag); | |||
| if (pvResult != NULL) | |||
| return pvResult; | |||
| } | |||
| else { | |||
| /* If the filename is not absolute then we wish to check along the | |||
| LADSPA_PATH path to see if we can find the file there. We do | |||
| NOT call dlopen() directly as this would find plugins on the | |||
| LD_LIBRARY_PATH, whereas the LADSPA_PATH is the correct place | |||
| to search. */ | |||
| pcLADSPAPath = getenv("LADSPA_PATH"); | |||
| if (pcLADSPAPath) { | |||
| pcStart = pcLADSPAPath; | |||
| while (*pcStart != '\0') { | |||
| pcEnd = pcStart; | |||
| while (*pcEnd != ':' && *pcEnd != '\0') | |||
| pcEnd++; | |||
| pcBuffer = malloc(iFilenameLength + 2 + (pcEnd - pcStart)); | |||
| if (pcEnd > pcStart) | |||
| strncpy(pcBuffer, pcStart, pcEnd - pcStart); | |||
| iNeedSlash = 0; | |||
| if (pcEnd > pcStart) | |||
| if (*(pcEnd - 1) != '/') { | |||
| iNeedSlash = 1; | |||
| pcBuffer[pcEnd - pcStart] = '/'; | |||
| } | |||
| strcpy(pcBuffer + iNeedSlash + (pcEnd - pcStart), pcFilename); | |||
| pvResult = dlopen(pcBuffer, iFlag); | |||
| free (pcBuffer); | |||
| if (pvResult != NULL) | |||
| return pvResult; | |||
| pcStart = pcEnd; | |||
| if (*pcStart == ':') | |||
| pcStart++; | |||
| } | |||
| } | |||
| } | |||
| /* As a last ditch effort, check if filename does not end with | |||
| ".so". In this case, add this suffix and recurse. */ | |||
| iEndsInSO = 0; | |||
| if (iFilenameLength > 3) | |||
| iEndsInSO = (strcmp(pcFilename + iFilenameLength - 3, ".so") == 0); | |||
| if (!iEndsInSO) { | |||
| pcBuffer = malloc(iFilenameLength + 4); | |||
| strcpy(pcBuffer, pcFilename); | |||
| strcat(pcBuffer, ".so"); | |||
| pvResult = dlopenLADSPA(pcBuffer, iFlag); | |||
| free(pcBuffer); | |||
| } | |||
| if (pvResult != NULL) | |||
| return pvResult; | |||
| /* If nothing has worked, then at least we can make sure we set the | |||
| correct error message - and this should correspond to a call to | |||
| dlopen() with the actual filename requested. The dlopen() manual | |||
| page does not specify whether the first or last error message | |||
| will be kept when multiple calls are made to dlopen(). We've | |||
| covered the former case - now we can handle the latter by calling | |||
| dlopen() again here. */ | |||
| return dlopen(pcFilename, iFlag); | |||
| } | |||
| /*****************************************************************************/ | |||
| void * | |||
| loadLADSPAPluginLibrary(const char * pcPluginFilename) { | |||
| void * pvPluginHandle; | |||
| pvPluginHandle = dlopenLADSPA(pcPluginFilename, RTLD_NOW); | |||
| if (!pvPluginHandle) { | |||
| fprintf(stderr, | |||
| "Failed to load plugin \"%s\": %s\n", | |||
| pcPluginFilename, | |||
| dlerror()); | |||
| return NULL; | |||
| } | |||
| return pvPluginHandle; | |||
| } | |||
| /*****************************************************************************/ | |||
| void | |||
| unloadLADSPAPluginLibrary(void * pvLADSPAPluginLibrary) { | |||
| dlclose(pvLADSPAPluginLibrary); | |||
| } | |||
| /*****************************************************************************/ | |||
| const LADSPA_Descriptor * | |||
| findLADSPAPluginDescriptor(void * pvLADSPAPluginLibrary, | |||
| const char * pcPluginLibraryFilename, | |||
| const char * pcPluginLabel) { | |||
| const LADSPA_Descriptor * psDescriptor; | |||
| LADSPA_Descriptor_Function pfDescriptorFunction; | |||
| unsigned long lPluginIndex; | |||
| dlerror(); | |||
| pfDescriptorFunction | |||
| = (LADSPA_Descriptor_Function)dlsym(pvLADSPAPluginLibrary, | |||
| "ladspa_descriptor"); | |||
| if (!pfDescriptorFunction) { | |||
| const char * pcError = dlerror(); | |||
| if (pcError) { | |||
| fprintf(stderr, | |||
| "Unable to find ladspa_descriptor() function in plugin " | |||
| "library file \"%s\": %s.\n" | |||
| "Are you sure this is a LADSPA plugin file?\n", | |||
| pcPluginLibraryFilename, | |||
| pcError); | |||
| return NULL; | |||
| } | |||
| } | |||
| for (lPluginIndex = 0;; lPluginIndex++) { | |||
| psDescriptor = pfDescriptorFunction(lPluginIndex); | |||
| if (psDescriptor == NULL) { | |||
| fprintf(stderr, | |||
| "Unable to find label \"%s\" in plugin library file \"%s\".\n", | |||
| pcPluginLabel, | |||
| pcPluginLibraryFilename); | |||
| return NULL; | |||
| } | |||
| if (strcmp(psDescriptor->Label, pcPluginLabel) == 0) | |||
| return psDescriptor; | |||
| } | |||
| } | |||
| /*****************************************************************************/ | |||
| /* EOF */ | |||
| @@ -1,32 +0,0 @@ | |||
| /* misc.c | |||
| Free software by Richard W.E. Furse. Do with as you will. No | |||
| warranty. */ | |||
| /*****************************************************************************/ | |||
| #include <dlfcn.h> | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| /*****************************************************************************/ | |||
| #include "ladspa.h" | |||
| #include "utils.h" | |||
| /*****************************************************************************/ | |||
| unsigned long | |||
| getPortCountByType(const LADSPA_Descriptor * psDescriptor, | |||
| const LADSPA_PortDescriptor iType) { | |||
| unsigned long lCount; | |||
| unsigned long lIndex; | |||
| lCount = 0; | |||
| for (lIndex = 0; lIndex < psDescriptor->PortCount; lIndex++) | |||
| if ((psDescriptor->PortDescriptors[lIndex] & iType) == iType) | |||
| lCount++; | |||
| return lCount; | |||
| } | |||
| @@ -1,127 +0,0 @@ | |||
| /* search.c | |||
| Free software by Richard W.E. Furse. Do with as you will. No | |||
| warranty. */ | |||
| /*****************************************************************************/ | |||
| #include <dirent.h> | |||
| #include <dlfcn.h> | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include <sys/types.h> | |||
| #include <unistd.h> | |||
| /*****************************************************************************/ | |||
| #include "ladspa.h" | |||
| #include "utils.h" | |||
| /*****************************************************************************/ | |||
| /* Search just the one directory. */ | |||
| static void | |||
| LADSPADirectoryPluginSearch | |||
| (const char * pcDirectory, | |||
| LADSPAPluginSearchCallbackFunction fCallbackFunction) { | |||
| char * pcFilename; | |||
| DIR * psDirectory; | |||
| LADSPA_Descriptor_Function fDescriptorFunction; | |||
| long lDirLength; | |||
| long iNeedSlash; | |||
| struct dirent * psDirectoryEntry; | |||
| void * pvPluginHandle; | |||
| lDirLength = strlen(pcDirectory); | |||
| if (!lDirLength) | |||
| return; | |||
| if (pcDirectory[lDirLength - 1] == '/') | |||
| iNeedSlash = 0; | |||
| else | |||
| iNeedSlash = 1; | |||
| psDirectory = opendir(pcDirectory); | |||
| if (!psDirectory) | |||
| return; | |||
| while (1) { | |||
| psDirectoryEntry = readdir(psDirectory); | |||
| if (!psDirectoryEntry) { | |||
| closedir(psDirectory); | |||
| return; | |||
| } | |||
| pcFilename = malloc(lDirLength | |||
| + strlen(psDirectoryEntry->d_name) | |||
| + 1 + iNeedSlash); | |||
| strcpy(pcFilename, pcDirectory); | |||
| if (iNeedSlash) | |||
| strcat(pcFilename, "/"); | |||
| strcat(pcFilename, psDirectoryEntry->d_name); | |||
| pvPluginHandle = dlopen(pcFilename, RTLD_LAZY); | |||
| if (pvPluginHandle) { | |||
| /* This is a file and the file is a shared library! */ | |||
| dlerror(); | |||
| fDescriptorFunction | |||
| = (LADSPA_Descriptor_Function)dlsym(pvPluginHandle, | |||
| "ladspa_descriptor"); | |||
| if (dlerror() == NULL && fDescriptorFunction) { | |||
| /* We've successfully found a ladspa_descriptor function. Pass | |||
| it to the callback function. */ | |||
| fCallbackFunction(pcFilename, | |||
| pvPluginHandle, | |||
| fDescriptorFunction); | |||
| } | |||
| else { | |||
| /* It was a library, but not a LADSPA one. Unload it. */ | |||
| dlclose(pcFilename); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /*****************************************************************************/ | |||
| void | |||
| LADSPAPluginSearch(LADSPAPluginSearchCallbackFunction fCallbackFunction) { | |||
| char * pcBuffer; | |||
| const char * pcEnd; | |||
| const char * pcLADSPAPath; | |||
| const char * pcStart; | |||
| pcLADSPAPath = getenv("LADSPA_PATH"); | |||
| if (!pcLADSPAPath) { | |||
| fprintf(stderr, | |||
| "Warning: You do not have a LADSPA_PATH " | |||
| "environment variable set.\n"); | |||
| return; | |||
| } | |||
| pcStart = pcLADSPAPath; | |||
| while (*pcStart != '\0') { | |||
| pcEnd = pcStart; | |||
| while (*pcEnd != ':' && *pcEnd != '\0') | |||
| pcEnd++; | |||
| pcBuffer = malloc(1 + pcEnd - pcStart); | |||
| if (pcEnd > pcStart) | |||
| strncpy(pcBuffer, pcStart, pcEnd - pcStart); | |||
| pcBuffer[pcEnd - pcStart] = '\0'; | |||
| LADSPADirectoryPluginSearch(pcBuffer, fCallbackFunction); | |||
| pcStart = pcEnd; | |||
| if (*pcStart == ':') | |||
| pcStart++; | |||
| } | |||
| } | |||
| /*****************************************************************************/ | |||
| /* EOF */ | |||
| @@ -1,80 +0,0 @@ | |||
| /* utils.h | |||
| Free software by Richard W.E. Furse. Do with as you will. No | |||
| warranty. */ | |||
| #ifndef LADSPA_SDK_LOAD_PLUGIN_LIB | |||
| #define LADSPA_SDK_LOAD_PLUGIN_LIB | |||
| /*****************************************************************************/ | |||
| #include "ladspa.h" | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /*****************************************************************************/ | |||
| /* Functions in load.c: */ | |||
| /* This function call takes a plugin library filename, searches for | |||
| the library along the LADSPA_PATH, loads it with dlopen() and | |||
| returns a plugin handle for use with findPluginDescriptor() or | |||
| unloadLADSPAPluginLibrary(). Errors are handled by writing a | |||
| message to stderr and calling exit(1). It is alright (although | |||
| inefficient) to call this more than once for the same file. */ | |||
| void * loadLADSPAPluginLibrary(const char * pcPluginFilename); | |||
| /* This function unloads a LADSPA plugin library. */ | |||
| void unloadLADSPAPluginLibrary(void * pvLADSPAPluginLibrary); | |||
| /* This function locates a LADSPA plugin within a plugin library | |||
| loaded with loadLADSPAPluginLibrary(). Errors are handled by | |||
| writing a message to stderr and calling exit(1). Note that the | |||
| plugin library filename is only included to help provide | |||
| informative error messages. */ | |||
| const LADSPA_Descriptor * | |||
| findLADSPAPluginDescriptor(void * pvLADSPAPluginLibrary, | |||
| const char * pcPluginLibraryFilename, | |||
| const char * pcPluginLabel); | |||
| /*****************************************************************************/ | |||
| /* Functions in search.c: */ | |||
| /* Callback function for use with LADSPAPluginSearch(). The callback | |||
| function passes the filename (full path), a plugin handle (dlopen() | |||
| style) and a LADSPA_DescriptorFunction (from which | |||
| LADSPA_Descriptors can be acquired). */ | |||
| typedef void LADSPAPluginSearchCallbackFunction | |||
| (const char * pcFullFilename, | |||
| void * pvPluginHandle, | |||
| LADSPA_Descriptor_Function fDescriptorFunction); | |||
| /* Search through the $(LADSPA_PATH) (or a default path) for any | |||
| LADSPA plugin libraries. Each plugin library is tested using | |||
| dlopen() and dlsym(,"ladspa_descriptor"). After loading each | |||
| library, the callback function is called to process it. This | |||
| function leaves items passed to the callback function open. */ | |||
| void LADSPAPluginSearch(LADSPAPluginSearchCallbackFunction fCallbackFunction); | |||
| /*****************************************************************************/ | |||
| /* Functions in misc.c: */ | |||
| /* Count the ports of a plugin matching a given type */ | |||
| unsigned long | |||
| getPortCountByType(const LADSPA_Descriptor * psDescriptor, | |||
| const LADSPA_PortDescriptor iType); | |||
| /*****************************************************************************/ | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif | |||
| /* EOF */ | |||