mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-03 16:09:39 +00:00
4fd57bbe3f
Original commit message from CVS: don't mix tabs and spaces
195 lines
5.4 KiB
C
195 lines
5.4 KiB
C
/* load.c
|
|
|
|
Free software by Richard W.E. Furse. Do with as you will. No
|
|
warranty. */
|
|
|
|
/*****************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <dlfcn.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <glib.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. */
|
|
|
|
/* thomasvs: I'm sorry, but I'm going to add glib stuff here.
|
|
* I'm appending logical values for LADSPA_PATH here
|
|
*/
|
|
|
|
pcLADSPAPath = g_strdup_printf ("%s:/usr/lib/ladspa:/usr/local/lib/ladspa",
|
|
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 ());
|
|
exit (1);
|
|
}
|
|
|
|
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);
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
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);
|
|
exit (1);
|
|
}
|
|
if (strcmp (psDescriptor->Label, pcPluginLabel) == 0)
|
|
return psDescriptor;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* EOF */
|