Re: [GnomeMeeting-devel-list] [PATCHES+CODE] PVideoInputManager support in pwlib+gm



Le jeu 31/07/2003 à 17:27, PUYDT Julien a écrit :
> * vidin_manager_dlopen.cxx
new version:
* beautified the sources a little;
* worked on the third FIXME: now the full list of plugins is scanned to
find if any of them may be of use (untested yet, since it is a "CLI
feature", that I don't know gm can use);
> * pwlib.patch
unchanged
> * gm.patch
unchanged

Snark
// system includes
#include <dlfcn.h>

// PWLib includes
#include <ptlib.h>
#include <ptlib/videoio.h>
#include <ptlib/vconvert.h>
#include <ptlib/pdirect.h>

struct video_plugin {
  const char *name;
  void *handle;
  PVideoInputDevice *(*Create)(void);
  PStringList (*DeviceNames)(void);
  struct video_plugin *next;
};

static struct video_plugin *plugins_list;  

PVideoInputManager::PVideoInputManager()
{
  PTRACE(3, "PVideoInputManager::PVideoInputManager called");
  if(plugins_list == NULL)
    LoadAllPlugins();
}


PVideoInputManager::~PVideoInputManager()
{
  // well, you're not really supposed to create one anyway...
}

void
PVideoInputManager::LoadAllPlugins()
{
  PTRACE(3, "Loading plugins...");
  LoadPluginDirectory("/usr/lib/pwlib/video");
}

void
PVideoInputManager::LoadPluginDirectory(PDirectory plugdir)
{
  PTRACE(4, "Considering loading plugins in " << plugdir);
  
  if(!plugdir.Open())
    {
      PTRACE(4, "the dir isn't accessible");
      return; // no love, no hope
    }
  
  do
    {
      (void)LoadPlugin(plugdir+plugdir.GetEntryName());
      // we don't really care if it worked...
    } 
  while(plugdir.Next());
  
}

BOOL
PVideoInputManager::LoadPlugin(PString filename)
{
      void *handle = NULL;
      struct video_plugin *plugin = NULL;
      
      plugin = (struct video_plugin *)malloc(sizeof(struct video_plugin));
      if(plugin == NULL)
	{
	  PTRACE(1, "PVideoInputManager::LoadPlugin: ENOMEM");
	  return FALSE;
	}

      PTRACE(5, "PVideoInputManager::LoadPlugin: " << filename);

      // first, we try to get a handle on the plugin
      handle=dlopen(filename, RTLD_LAZY);
      if(handle == NULL)
	{
	  PTRACE(3, "PVideoInputManager::LoadPlugin: dlerror=" << dlerror());
	  free(plugin);
	  return FALSE;
	}
      plugin->handle = handle;

      // second, we try to get its name
      char *(*getname)(void);
      getname = (char *(*)())dlsym(handle, "plugin_getname");
      if(getname == NULL)
	{
	  PTRACE(3, "PVideoInputManager::LoadPlugin: dlerror=" << dlerror());
	  goto wrong;
	}
      plugin->name = (*getname)();
	
      // third, we try to get its creator
      PVideoInputDevice *(*Create)();
      Create = (PVideoInputDevice *(*)(void))dlsym(handle,"plugin_create");
      if(Create == NULL)
	{
	  PTRACE(3, "PVideoInputManager::LoadPlugin: dlerror=" << dlerror());
	  goto wrong;
	}
      plugin->Create = Create;

      // fourth, we try to get its devices lister
      PStringList (*DeviceNames)();
      DeviceNames = (PStringList (*)(void))dlsym(handle, "plugin_getdevices");
      if(DeviceNames == NULL)
	{
	  PTRACE(3, "PVideoInputManager::LoadPlugin: dlerror=" << dlerror());
	  goto wrong;
	}
      plugin->DeviceNames = DeviceNames;
   
      // finally, since we got all we wanted, we just add it to the list!
      plugin->next = plugins_list;
      plugins_list = plugin;
 
      PTRACE(5, "PVideoInputManager::LoadPlugin: succeeded");
     
      return TRUE;
 wrong: 
      free(plugin);
      (void)dlclose(handle);
      return FALSE;
}

PVideoInputDevice*
PVideoInputManager::GetDevice(PString name)
{ 
  for(struct video_plugin *ptr=plugins_list;
      ptr != NULL;
      ptr = ptr->next)
    {
      if(strcmp(name, ptr->name) == 0)
	return ptr->Create();
    }

  return NULL;
}

PVideoInputDevice*
PVideoInputManager::GetOpenedDevice(PString devName, BOOL flag)
{
  char driver[11]; // FIXME! Only ten chars for the driver name...

  if(plugins_list == NULL)
    LoadAllPlugins();

  if(sscanf(devName, "%s", &driver) == 1)
    { // looks like a nice devName
      PString filename = devName.Right(strlen(devName)-strlen(driver)-1);
      // FIXME! this computation is awful!

      PVideoInputDevice *dev = GetDevice(driver);

      if(dev != NULL && dev->Open(filename, flag))
	return dev;

      if(dev != NULL)
	delete dev;

      return NULL;
    }
  else
    { // doesn't look like a nice devName
      // (that can be a user on CLI, who wants us to open /dev/video3.14)

      // FIXME: there is a nicer solution to implement that,
      // but my pattern-matching abilities are quite small,
      // as the previous fixme must have proven: search through the list of
      // devices names we get from GetInputDeviceNames, and only ask to those
      // drivers that claimed they could handle devName.

      for(struct video_plugin *ptr=plugins_list;
	  ptr != NULL;
	  ptr = ptr->next)
	{
	  PVideoInputDevice *dev=ptr->Create();
	  if(dev != NULL && dev->Open(devName, flag))
	    return dev;

	  if(dev != NULL)
	    delete dev;
	}

      return NULL;
    }
}

PStringList
PVideoInputManager::GetInputDeviceNames()
{
  PTRACE(3, "PVideoInputManager::GetInputDeviceNames called");
 
  if(plugins_list == NULL)
    LoadAllPlugins();

  // we get through all the plugin lists, and add the name as a prefix,
  // to be able to track down which takes care of what
  
  PStringList Result;
 
  for(struct video_plugin *ptr=plugins_list;
      ptr != NULL;
      ptr=ptr->next)
    {
      PStringList tmplist = ptr->DeviceNames();

      for (PINDEX i = 0; i < tmplist.GetSize(); i++)
	{
	  Result.AppendString((PString)ptr->name+" "+tmplist[i]);
	}
    }
 
  return Result;

}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]