Rygel is written completely in the Vala programming language, which generates GObject-based C code. Large parts of the code are available via shared-library APIs (such as librygel-server and librygel-renderer-gst) which are generally expected to be used via the documented C API.
See the Rygel Architecture Diagram.
The following sections describe the interaction of Rygel's parts during UPnP operations.
At startup, Rygel performs the following steps:
Prepares RygelMetaConfig, for later use, adding specific Configuration implementations that get the information from:
- Environment variables
- Command line options
- The configuration file
- Sets up UNIX signal handlers to allow clean shutdown, sending SSDP BYEBYE messages on SIGINT or SIGTERM.
- Acquires the D-Bus name to ensure only one instance of the Rygel executable is running. If another instance is blocking the name it is shut down.
Creates a UPnP context manager (GUPnPContextManager) to watch for appearing/disappearing network devices.
Creates the plugin loader (RygelPluginLoader).
- Starts loading plugins.
Network Devices Appearing
When a network device appears, Rygel is notified by the GUPnPContextManager and then:
Checks if it should listen on this network interface by checking its configuration, via RygelMetaConfig.
Iterates over the plugin list and creates a RygelRootDevice for each plugin from that factory.
Network Devices Disappearing
When a network device disappears, Rygel is notified by the GUPnPContextManager and then:
When a client application calls the UPnP Browse action on a Rygel server device, by sending a UPnP message, Rygel:
Creates a new instance of RygelBrowse, parsing the arguments and verifying the parameters of the call.
If the object is found, depending on the type of the browse, Rygel will either return the metadata of the object by serializing it directly or, if the object is a container, Rygel will get its children using RygelMediaContainer.get_children() and serialize the list of results.
Searching is very similar to browsing. When a client application calls the UPnP Search action on a Rygel server device, by sending a UPnP message, Rygel:
Handles the "action-invoked::Search" signal emitted by GUPnPService, in
Creates a new instance of RygelSearch, parsing the arguments and verifying the parameters of the call.
If the object is found, it will use RygelSearchableContainer.search() to execute the search query and serialize the returned list if any. The search is either implemented by the plugin or done by a recursive tree walk, using the default implementation in RygelSearchableContainer.simple_search().
Uploading is a two-step process. First an object needs to be created with the UPnP CreateObject call, then the data needs to be uploaded, either by using the ImportResource UPnP call, requiring the data to be available via HTTP, or by using HTTP POST, posting to the res@importURI returned by the CreateObject call.
When a client application calls the UPnP CreateObject action on a Rygel server device, by sending a UPnP message, Rygel:
Handles the "action-invoked:CreateObject" signal emitted by GUPnPService.
- It then fetches the parent container of the to-be-created item, checking various preconditions on that parent container such as:
Whether clients may create child items in this container (The Upload flag in the OCM flags).
- Whether the class of the item to be created matches the ones allowed in the container.
If the container has the special DLNA.ORG_AnyContainer ID, it will use the RygelSearchableContainer.search() function to search for a suitable container to upload to.
- The code waits (maximim 5 seconds) for the item to show up in the container, giving the backend time to add it.
The item is serialized back to DIDL-Lite using GUPnPDIDlLiteWriter to be sent to the caller.
If the container has the special DLNA.ORG_AnyContainer ID, the item is also scheduled for automatic removal in the RygelItemRemovalQueue after 35 seconds (as specified by DLNA) if no data upload happens.
Uploading with HTTP POST
The client receives a DIDL-Lite snippet from Rygel in the response of the CreateObject UPnP call containing a UPnP res node carrying an importURI attribute.
- (A res node describes a UPnP resource, such as a URI and some specific meta-data.)
- The client uses HTTP POST to send data to the Rygel server's URI.
If the SoupMessage emits its "got-body" signal then the temporary file is moved to the real file.
RygelHTTPPost waits for 5 seconds for the backend to analyze the file and update the item information.
Uploading with ImportResource
- The client receives a DIDL-Lite snippet with a res node carrying an importURI attribute
The client makes the data to be imported available on a HTTP server and calls ImportResource with the local URI and the URI from importResource
GUPnPService emits "action-invoked:ImportResource"
RygelImportResource does some sanity checks on the URI and item
RygelImportResource creates a HTTP GET request for the source URI, creates a file to save the content to and connects to the SoupMessage's "got-chunk" signal, writing the data chunks to the temporary file.
If the SoupMessage emits its "got-body" signal then the operation is concluded.
In principle, rendering is the process of setting an URI to play and then calling play.
- The client calls SetAVTransportURI.
GUPnPService emits "action-invoked:SetAVTransportURI"
If the URI is HTTP or HTTPS, RygelAVTransport issues a HTTP HEAD request to query some DLNA parameters and the content-type from the DMS and check the URL for accessibility.
If the URI is accessable and the content type is supported, URI and metadata will be set on the RygelPlayerController. If the URI is a playlist, RygelPlayerController parses the playlist and sets the content type and DLNA features of the first item on the player. Otherwise the content type as well as DLNA features are passed to the RygelMediaPlayer instance directly.
- The client calls Play.
GUPnPService emits "action-invoked:Play".