| @@ -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 */ | |||||