Switch to unified view

a/src/mediaserver/00doc.txt b/src/mediaserver/00doc.txt
1
= Upmpdcli Mediaserver notes
1
= Upmpdcli Mediaserver notes
2
2
3
A mediaserver process is create by the main upmpdcli process if a call to
3
A Media Server instance is created by the main upmpdcli process if a call
4
ContentDirectory::mediaServerNeeded() returns true, which occurs if the
4
to ContentDirectory::mediaServerNeeded() returns true, which occurs if the
5
root directory of the Content Directory would not be empty (see further for
5
root directory of the Content Directory would not be empty (see further for
6
how this is determined.
6
how this is determined).
7
8
Depending on the command line option, the Media Server can be as a separate
9
device/process (the default, which also allows to run a Media Server only,
10
with no Renderer device), or as an embedded device of the main Media
11
Renderer device. Very few Control Points can handle the latter approach,
12
and the code was kept mostly because we can.
7
13
8
== ContentDirectory.cxx
14
== ContentDirectory.cxx
9
15
10
This file contains the libupnpp callbacks, and the root directory creation
16
This file contains the libupnpp callbacks, and the root directory creation
11
code, together with plugin activation and dispatch code.
17
code, together with plugin activation and dispatch code.
12
18
13
=== Root directory creation
19
=== Root directory creation
14
20
15
It was originally thought that this module would see several different
21
It was originally thought that this ContentDirectory.cxx would see several
16
provider modules, so that it would be natural that it builds the root
22
different provider modules, so that it would be natural that it builds the
17
directory (with top entries for each of the modules).
23
root directory (with top entries for each of the modules).
18
24
19
What happened finally is that there is only one provider module,
25
What happened finally is that there is only one provider module,
20
plgwithslave.cxx, so that the root directory creation code, which has
26
plgwithslave.cxx, so that the root directory creation code, which has
21
knowledge of its internal should probably moved to plgwithslave.cxx:
27
knowledge of its internals should probably moved to plgwithslave.cxx:
22
if other modules were added, we'd need an interface so that they each can
28
if other modules were added, we'd need an interface so that they each can
23
provide their entries for the root dir. As it is, things can stay this way.
29
provide their entries for the root dir. As it is, things can stay this way.
24
30
25
ContentDirectory::makerootdir(), which should be in plgwithslave, uses the
31
ContentDirectory::makerootdir(), which should be in plgwithslave, uses the
26
plgwithslave plugins names to create root entries.
32
plgwithslave plugin names to create root entries.
27
33
28
The plugin names are currently used in quite a few places. For a module
34
The plugin names are currently used in quite a few places. For a module
29
named 'plgname':
35
named 'plgname':
30
36
31
 - As the name of a subdirectory under cdplugins, used to enumerate the
37
 - As the name of a subdirectory under cdplugins, used to enumerate the
...
...
46
(capitalized), with objid 0$plgname$
52
(capitalized), with objid 0$plgname$
47
53
48
54
49
=== Plugin activation and dispatch
55
=== Plugin activation and dispatch
50
56
51
When browse is requeted for an objectid beginning with 0$plgname$, the code
57
When the browse method is called for an object Id beginning with
52
looks up (Internal::pluginforapp(), and possibly creates
58
0$plgname$, the code looks up (Internal::pluginforapp(), and possibly
53
(Internal::pluginfactory()) the plugin. Currently, this is always a
59
creates (Internal::pluginfactory()) the plugin. Currently, this is always a
54
PlgWithSlave object, created with 2 parameters: the service name (which it
60
PlgWithSlave object, created with 2 parameters: the service name (which it
55
will use to find and exec the python module), and a service interface which
61
will use to find and exec the python module), and a service interface which
56
it can use to request information from the ContentDirectory.
62
it can use to request information from the ContentDirectory.
57
63
58
The knowledge that all of a plugin's object ids must begin with 0$plgname$
64
The knowledge that all of a plugin's object ids must begin with 0$plgname$
...
...
79
   ContentDirectory would just keep a mapping of object id to plugin.
85
   ContentDirectory would just keep a mapping of object id to plugin.
80
86
81
But, things are ok, even if a bit difficult to understand (hence this doc),
87
But, things are ok, even if a bit difficult to understand (hence this doc),
82
as long as all providers are modules under plgwithslave.
88
as long as all providers are modules under plgwithslave.
83
89
90
libupnp addr and port: these are retrieved in the ContentDirectory init,
91
and the plugins get it through service interface calls (getupnpaddr/port())
92
The host part is then communicated to the subprocesses through the environment
93
(UPMPD_HTTPHOSTPORT), but the port part is not used: the microhttpd port is
94
used instead. The port part would have been used if we had been using the
95
libupnp miniserver, which we don't because microhttpd can do redirects.
84
96
97
The uprcl local media server plugin does not use UPMPD_HTTPHOSTPORT at all,
98
because it uses its own HTTP server (started on uprclhostport)
85
99
100
== HTTP server
101
102
The resource URLs are initially generated by the plugins, and possibly
103
transformed when they are actually requested.
104
105
There are 3 possibilities for the actual HTTP server:
106
 - The libupnp miniserver (unused at this time)
107
 - An internal microhttpd instance (only doing redirects at this time)
108
 - An external server.
109
 
110
The 3 streaming service modules (tidal/qobuz/gmusic) currently work in the
111
same way:
112
 - They use the port supplied from plgwithslave which is the one on which
113
   the microhttpd instance is listening. The URIs are like
114
   http://host:port/someplugin/xxx.mpr?trackId=tid
115
 - The microhttpd request method only does redirects. When it gets a
116
   connection, it parses the above url, passes it to the appropriate plugin
117
   (as per the path), which provides the actual streaming service URL, to
118
   which the client is redirected. An hypothetical client which would not
119
   handle redirects would be out of luck.
120
 - No configuration data is required (the microhttpd port could be
121
   configured with plgmicrohttpport, default 49149).
122
123
The miniserver port value which the plgwithslave constructor receives and
124
stores in upnpport is not used, as the miniserver itself
125
126
The local media server plugin uses a separate http service, which began as
127
a completely external server (e.g. an Apache server), but is now more
128
conveniently the embedded Python server. The URLS which are generated in
129
the directory resource records point directly to the HTTP server host/port,
130
there is no redirection through the microhttpd server (this is the big
131
difference with the streaming service plugins.
132
133
The paths still need translation (they include the plugin name as prefix
134
for diag purposes, and there is a map between recoll and http paths). The
135
translation routine is now part of the Python request handler, but would
136
need to be restored if we went back to using an external server.
137
138
The following configuration data is used:
139
   The host and port for the HTTP server. This is used in generated URLs
140
   and as parameter to start the Python server:
141
      uprclhost = 192.168.4.4:8080
142
   Paths translation between the Recoll file paths (as used for topdirs)
143
   and the paths relative to the HTTP server document root, e.g.:
144
      uprclpaths = /y/av/mp3:/mp3
145
   The path map was really useful with Apache, much less so with the
146
   internal server, but has been kept as a way to define the file system
147
   area allowed for access: any path not in the map will be rejected.
148
   
149
In the first implementation, the external HTTP server had to be separately
150
configured to serve the media directories. The internal server uses the
151
config data.
152