= Upmpdcli Mediaserver notes
A mediaserver process is create by the main upmpdcli process if a call to
ContentDirectory::mediaServerNeeded() returns true, which occurs if the
root directory of the Content Directory would not be empty (see further for
how this is determined.
== ContentDirectory.cxx
This file contains the libupnpp callbacks, and the root directory creation
code, together with plugin activation and dispatch code.
=== Root directory creation
It was originally thought that this module would see several different
provider modules, so that it would be natural that it builds the root
directory (with top entries for each of the modules).
What happened finally is that there is only one provider module,
plgwithslave.cxx, so that the root directory creation code, which has
knowledge of its internal should probably moved to plgwithslave.cxx:
if other modules were added, we'd need an interface so that they each can
provide their entries for the root dir. As it is, things can stay this way.
ContentDirectory::makerootdir(), which should be in plgwithslave, uses the
plgwithslave plugins names to create root entries.
The plugin names are currently used in quite a few places. For a module
named 'plgname':
- As the name of a subdirectory under cdplugins, used to enumerate the
plugins on startup.
- As the name of the main plugin Python module, named
cdplugins/plgname/plgname-app.py
- As an element of the object ids belonging to this module (all beginning
with 0$plgname$)
- As an element of the resource URIs generated by the module (all
beginning with /plgname).
On startup makerootdir() walks the cdplugins directory (skipping
pycommon). For each subdirectory, it decides that the module is configured
if there is a variable named 'plgnameuser' in the upmpdcli configuration
file (so even plugins without users should have such a variable).
If the plugin is configured, makerootdir() creates an entry named Plgname
(capitalized), with objid 0$plgname$
=== Plugin activation and dispatch
When browse is requeted for an objectid beginning with 0$plgname$, the code
looks up (Internal::pluginforapp(), and possibly creates
(Internal::pluginfactory()) the plugin. Currently, this is always a
PlgWithSlave object, created with 2 parameters: the service name (which it
will use to find and exec the python module), and a service interface which
it can use to request information from the ContentDirectory.
The knowledge that all of a plugin's object ids must begin with 0$plgname$
is spread in multiple places in the C++ and Python code.
=== ContentDirectory service interface
ContentDirectory provides a number of service methods to its
providers. They are defined in cdplugins/cdplugin.hxx:CDPluginServices, an
instance of which is passed to the plugin constructor. See the file for
more details.
=== Notes
At the moment, the interface between ContentDirectory and the plgwithslave
plugin is a bit of a mess:
- There is a lack of interfaces which would be needed if other modules
than plgwithslaves were added.
- There is too much knowledge of the plgwithslave internals in
ContentDirectory.
- Both problems are linked.
- Probably plgwithslave should provide the root entries, and
ContentDirectory would just keep a mapping of object id to plugin.
But, things are ok, even if a bit difficult to understand (hence this doc),
as long as all providers are modules under plgwithslave.