[mythtv] Revamping the plugin system.

J. Donavan Stanley jdonavan at gorpe.com
Thu Nov 27 10:29:51 EST 2003


While working on the CD monitoring system I quickly realized that I couldn't accomplish my goals for it without resorting to ugly hacks.  So I took a step back and started from square one so that I could get the foundation in place first.  To that end I've been working on a  revamped plugin system for MythTV to allow for new types of plugins and a more complete plugin framework.

I started with "Yehia" as a baseline, and made several modifications so that it fits into MythTV (mostly converting it to use Qt objects instead of SigC++ and the like).  Under the new system, each plugin has a single entry point which returns a pointer to an object derived from "Plugin".  This allows us to define new types of plugins rather easily since we simply need to define an interface derived from Plugin.  

The plugin directory structure has been changed to support a naming scheme that classifies plugins, as well as allowing for version dependent and independent plugins for example.  ${PREFIX}/plugins/channel/lirc.so would refer to a version independent channel changer plugin, where as ${PREFIX}/plugins/0.13/channel/lirc.so would refer to the same plugin that's only guaranteed to work with version .13.  In addition to the two main plugin trees plugins can also be loaded from ${HOME}/${PREFIX}/plugins (i.e. ~mthtv/mythtv/plugins) with both version dependent and independant types just like the main tree. The new plugin manager has a mechanism to automaticly discover plugins.  It can walk the various plugin trees to see what's available in them. To illustrate the search sequence when you request a plugin to be loaded here's some output from my test app:
	Loading plugin: test
	Trying: /home/mythtv/.mythtv/0.13/plugins/test FAILED.
	Trying: /home/mythtv/.mythtv/0.13/plugins/libtest FAILED.
	Trying: /usr/local/mythtv/0.13/plugins/test FAILED.
	Trying: /usr/local/mythtv/0.13/plugins/libtest FAILED.
	Trying: /home/mythtv/.mythtv/plugins/test FAILED.
	Trying: /home/mythtv/.mythtv/plugins/libtest FAILED.
	Trying: /usr/local/mythtv/plugins/test OK.

As you can see, this allows us to put test versions of plugins in the user directory plguin tree to try them out without mucking around with our base install.

Plugins are grouped into different archetypes, defined as pure virtual classes derived from Plugin.  An example is the "Application" type which supports "run", and "setup" functions (look familiar?).  To implement a new application one simply needs to create a shared library that exposes myth_PLUGINNAME_init (i.e. myth_mythmusic_init), that function should return a pointer to an object derrived from one of the archetypes.  Loading of legacy plugins is supported by some special case code in the PluginLoader that uses a LegacyPlugin type derived from the application type and delegates through the exposed functions in the old plugin.

All plugins, have some basic attributes:
	Type - An enum indicating the type of plugin it is.  Used internaly (i.e. PIT_APPLICATION)
	SubType - A type dependent enum. (i.e. APPTYPE_LEGACY)
	Name - A human readable name. (i.e. MythMusic)
	Description - Self explanitory.

I've currently got this basic framework up and running as libmythplugin on my dev box.  Currently only the application and legacy plugins are defined and nothing has been integrated into libmyth yet.  I'm pretty much holding off on the next steps, to see if there's enough interest in this approach.   The last thing I want to do is invest lots of time only to be told "thanks but no thanks".

If this is green lighted I'll move forward with integrating everything into libmyth and mythfrontend as follows:
	- A new table will be added that contains: Plugin, PluginName, PluginDescription, EnabledFlag
	- On startup Myth will go through a discovery phase locating new plugins and adding them to the table, as well as removing non-existent ones.
	- During this discovery phase the user will be shown the name / description of each newly discovered plugin and be given the chance to enable it.
	- A setup screen will be added that will allow the user to enable / disable installed plugins.


Once all of this is in place it opens up a lot of possibilities... For example I've been tossing around the idea of having input plugins so that you can have plugins for lirc, UIRT2 etc.  Channel changing can be done via plugins as well as could filters.  Lots of the existing architecture could be broken out and componentized...


One immediate area I'd like to "pluginize" is the handling of removable media.  I'd like to add a "MediaManager" object to the frontend that talked to "MediaMonitor" and "MediaHandler" plugins.  A MediaMonitor plugin would operate in a separate thread watching a given set of media devices (i.e. CD/DVD, Compact Flash etc).  Whenever media is inserted it would send an event to the MediaManager indicating the type of media as well as it's path/device.

The MediaMonitor would then query the various MediaHandler plugins to see which ones handled this type of media and what possible actions they support for the media in the form of ActionName, ActionDescription (i.e. "ImportAudio", "Scan this CD for new music files to add to your collection." ).  The user would then be presented with a pop up menu that looked something like this:

	You've just inserted a data CD what could you like to do?

	- Scan this CD for new music files to add to your collection. -
	- Scan this CD for music files and play them. -
	- Scan this CD for video files to add to your collection. -
	- Scan this CD for new images to add to your collection. -

	_ Always perform this action for this type of media.

The MediaMonitor would take the users selection and call PerformAction on the proper plugin.


Sorry this is so long.  But even as long as it is, I've still probably missed something or glossed over some important bit...





More information about the mythtv-dev mailing list