= 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.