Thumbnail management DBus specification

This is a Draft

Authors

Core authors

  • Philip Van Hoof <philip at codeminded dot be>

  • Rob Taylor <rob.taylor at codethink dot co dot uk>

  • Jannis Pohlmann <jannis at xfce dot org>

Language and spelling improvements

  • Tinne Hannes <tinne dot hannes at gmail dot com>

  • Spellchecks are a bit outdated as sections got added. Feel free to contribute spell fixes (this is a wiki).

Introduction

The thumbnail management DBus specification is a standardized DBus API to deal with thumbnailing.

With a DBus specification for thumbnail management, applications don't have to implement thumbnail management themselves. If a thumbnailer is available they can delegate thumbnail work to a specialized service. The service then callbacks when it has finished generating the thumbnail.

Delegating this work has advantages:

  • No need to link complex pieces of software into all the applications that want to work with thumbnails
  • Possibility for thumbnailers of closed formats (which might have patents) to coexist with free software desktop applications that (just) want to display the files as thumbnails.
  • Reuse of existing infrastructure instead of making all applications reinvent it
  • Complexity of a LIFO queue and setting I/O and scheduling priorities for background thumbnailing is no longer the responsibility of the application developer

Delegation of this work to a service doesn't mean that the service is necessarily the only process writing in the directory specified by the Thumbnail Managing Standard (in case of a typical platform). File managers that want to have full control over their real-time thumbnail mechanisms don't need to go through the service. Although they can consume the service, too. When using the Thumbnail Managing Standard it requires those application developers to use the rename() syscall correctly. Failing to use this correctly might introduce race conditions with the thumbnail service.

Dependencies of this specification

Issues To Solve

There are some issues to solve to make this work correctly. Specifically these issues are:

  • Requesting to create a thumbnail for a thumbnail-able file
  • Informing the system of a deletion of a thumbnail-able file
  • Informing the system of a move of a thumbnail-able file to another location
  • Enabling third party thumbnailers to register a thumbnailer for a specific MIME type
  • Asynchronous handling and prioritizing
  • Large amounts of thumbnail-able items, reducing the amount of DBus messages
  • Requiring the service to be activatable (requirement to install a service file)
  • Requiring third party thumbnailers to be activatable (requirement to install a service file)
  • Requiring third party thumbnailer to register themselves
  • Implementation recommendations about registration of specialized thumbnailers
  • VFS issues, clients might have a different VFS layer as the Thumbnailer service

All these things are discussed and solutions are presented in the next chapters.

VFS issues

It's not possible today to specify that all URIs of all VFS systems can be guaranteed to work by specification. Therefore is only the file:/// scheme of URIs guaranteed to work cross desktop. Other URI schemes will most likely work if your client software shares the host's VFS layer with you.

Generic thumbnailer

All requests for thumbnails, a.k.a. queuable tasks, are received by the generic thumbnailer service.

This service ...

  • Proxies the request to one or more specialized thumbnailers and emits Ready signals when those specialized ones are finished thumbnailing or;

  • Emits Ready signals for example when the thumbnail is already cached or;

  • Emits Ready signals when it solved thumbnailing internally (there was no specialized thumbnailer available but the generic thumbnailer was able to create thumnbails for the MIME type) or;

  • Immediately returns with a infrastructure failure or;
  • Emit failures in a signal called Error;

  • Provides GetSupported and GetSchedulers methods to query supported URI schemes, MIME types and available schedulers.

When the generic thumbnailer service proxies it to specialized thumbnailers, it must make sure that it doesn't send files to the specialized thumbnailer's Queue method which the specialized thumbnailer can't handle. Refer to the section Specialized thumbnailers below to learn about the generic thumbnailer knowing which MIME types a specialized thumbnailer can handle.

It's allowed but not required to send files that are already thumbnailed to the Queue method of the specialized thumbnailer. It's up to the specialized thumbnailer to determine what this means: does is have to recreate the thumbnail or not? More information about the Queue method of specialized thumbnailers can be found in the section Specialized thumbnailers.

Whenever the generic thumbnailer knows that a thumbnail is finished, it must send a Ready signal. Preferably but not required it does this as soon as possible. It can, for example, send one Ready signal with all the thumbnails that are already cached, and then individual Ready signals each time when a thumbnail was created.

The D-Bus service file

In order for the generic thumbnailer to be activatable over D-Bus, it is required to install a D-Bus service file. This file should have a unique name and should be versioned. An example filename for version 1 of an implementation called YourProject could be org.yourdomain.YourProject.Thumbnailer1.service. The format specified in the desktop entry specification is used to specify the D-Bus interface and the daemon executable. For version 1.x of this spec, this would be:

[D-BUS Service]
Name=org.freedesktop.thumbnails.Thumbnailer1
Exec=your-thumbnailerd

Whether you want to append the version to the executable filename as well is up to you. Depending on how the specification is implemented, different versions of the spec could be implemented in the same daemon or in separate executables.

The service file needs to be installed into $XDG_DATA_DIRS/dbus-1/services/. Check out The basedir specification for more information about $XDG_DATA_DIRS. In a build environment that can use pkg-config use this command:

~$ pkg-config --variable session_bus_services_dir dbus-1
/usr/share/dbus-1/services
~$ 

org.freedesktop.thumbnails.Thumbnailer1

<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
         "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
 <node name="/org/freedesktop/thumbnails/Thumbnailer1">
  <interface name="org.freedesktop.thumbnails.Thumbnailer1">

Request the creation of thumbnails

    <method name="Queue">
      <arg type="as" name="uris" direction="in" />
      <arg type="as" name="mime_types" direction="in" />
      <arg type="s" name="flavor" direction="in" />
      <arg type="s" name="scheduler" direction="in" />
      <arg type="u" name="handle_to_dequeue" direction="in" />
      <arg type="u" name="handle" direction="out" />
    </method>

If you want just one file to be thumbnailed, you only put one URI in uris. You can, however, put a lot of files in the array. Especially if you have a large amount of files to thumbnail, it's preferred to group them together rather than sending an individual request per file. In case your request is truly large, consider using an appropriate scheduler. For more information about this refer to the GetSchedulers method below.

Parameters:

  • uris: The uris that you pass must be URIs, not paths. This means that for a file on the local filesystem you use file:///home/user/Desktop/Screenshot.png instead of /home/user/Desktop/Screenshot.png.

  • mime_types: The mime_types is of the same size as the uris. This field contains the mime-types for the items in uris (item n in mime_types corresponds to item n in uris). For example mime_types[0] = "image/jpeg" for uris[0] = "file:///home/user/image.jpeg".

  • flavor: The flavor that should be made (eg. normal). A list of supported flavors can be queried with the GetFlavors method documented later in this specification.

  • scheduler: The preferred scheduler to be used for processing the thumbnail request. A list of supported schedulers can be queried with the GetSchedulers method documented later in this specification. Special schedulers can be used to optimize the overall performance or to prioritize certain thumbnail requests. If your implementation is not interested in this, it can pass "default" here, which has to be supported by all generic thumbnailers and which simply leaves the decision which scheduler to use for the request up to the thumbnailer.

  • handle_to_dequeue: If you pass a number different than 0 to handle_to_dequeue, the request which yielded that handle is dequeued before a new request is queued. Passing handle_to_dequeue is similar to issuing a Dequeue (see below) before issuing a Queue. It is made possible to pass it during Queue so that you can reduce the amount of DBus traffic.

This method always returns a handle different than 0. The returned handle can be used in a subsequent Queue as handle_to_dequeue or in a Dequeue request.

Cancel/Dequeue thumbnail requests

    <method name="Dequeue">
      <arg type="u" name="handle" direction="in" />
    </method>

The Dequeue method removes thumbnail requests from the queue. A service implementation is only guaranteed to cancel requests that have not started processing yet when it receives the Dequeue request. A service implementation may cancel an in-progress request if possible, but clients should not depend on this behavior being available. Although it's recommended that the thumbnailer won't do this, a queued request that is dequeued can still cause Ready and Error signals to be emitted before the Finished signal. The Started and Finished signals will always be emitted (for all dequeued items).

Parameters:

  • handle: The handle that got returned to you from an earlier Queue call.

Thumbnails are ready for use

    <signal name="Ready">
      <arg type="u" name="handle" />
      <arg type="as" name="uris" />
    </signal>

Emitted when one or more thumbnails are ready. Every URI for which a thumbnail was generated successfully must be reported using this signal. It's possible that the thumbnailer uses dbus_message_set_destination for emits of this signal (set to the sender of the Queue method). It is allowed for service implementations to emit multiple Ready signals for a single Queue invocation.

Parameters being passed to you:

  • handle: The handle that was returned to you from an earlier Queue call.

  • uris: The original uris that were passed to the thumbnailer via the Queue method and for which thumbnails were generated successfully. To find the paths to the generated thumbnails on a typical platform, use the thumbnail managing standard.

Enqueued request is started to be processed

    <signal name="Started">
      <arg type="u" name="handle" />
    </signal>

This signal is emitted when an enqueued request is started to be processed. Started and Finished will be emitted for all requests that were made via the Queue method before the first and after the last URI of a request is or was processed. This also includes requests that failed entirely because none of its URIs or MIME types are supported. It's possible that the thumbnailer uses dbus_message_set_destination for emits of this signal (set to the sender of the Queue method). Started will be emitted only once for each Queue call.

Parameters being passed to you:

  • handle: The handle that was returned to you from an earlier Queue call.

Enqueued request is completed

    <signal name="Finished">
      <arg type="u" name="handle" />
    </signal>

Emitted when a request queued earlier with the Queue method has been completed. This is the case when all URIs that were part of the request have been processed. It is irrelevant whether they succeeded or not. Started and Finished must emitted in any case before the first and after the last URI of a request is or was processed. It's possible that the thumbnailer uses dbus_message_set_destination for emits of this signal (set to the sender of the Queue method). The Finished signal will be emitted only once for each Queue call. If Finished is emitted but not all uris of the Queue were reported back to the client via an Error or Ready signal, then this means that the request was dequeued. As dequeuing may happen at any time, clients have to make sure to handle this scenario appropriately.

Parameters being passed to you:

  • handle: The handle that was returned to you from an earlier Queue call.

Error occured

    <signal name="Error">
      <arg type="u" name="handle" />
      <arg type="as" name="failed_uris" />
      <arg type="i" name="error_code" />
      <arg type="s" name="message" />
    </signal>

Emitted when an error occurred when processing a URI of a request queued earlier with Queue. An Errorsignal does not necessarily mean that the entire queued request is aborted and that there will be no further Ready/Error signals emitted for the request. It is normal behaviour to emit multiple errors per queued request. It is on the other hand also normal to emit just one error and have all URIs that failed in failed_uris. Despite one or more Error signals, Started and Finished will always be emitted for every request queued with Queue. It's possible that the thumbnailer uses dbus_message_set_destination for emits of this signal (set to the sender of the Queue method).

Error signals emitted by specialized thumbnailers, to which the generic thumbnailer delegates its work, are propagated to clients of the generic thumbnailer.

Parameters being passed to you:

  • handle: The handle that was returned to you from an earlier Queue call.

  • failed_uris: The URIs that failed and that caused this error to occur. This can but does not necessarily contain all URIs that were passed to the corresponding Queue call. The URIs may also be listed in a different order.

  • error_code: The list of error codes defined in this specification can be seen below. Other error codes are not defined yet and may not be used.

    • Error code

      Meaning

      0

      The URIs in failed_uris have (currently) unsupported URI schemes or MIME types.

      1

      The connection to a specialized thumbnailer could not be established properly.

      2

      The URIs in failed_uris contain invalid image data or data that does not match the MIME type.

      3

      The URIs in failed_uris are thumbnail files themselves. We disallow infinite recursion.

      4

      The thumbnails for URIs in failed_uris could not be saved to the disk.

      5

      Unsupported flavor requested

  • message: Additional textual information about the error, like a detailed description of its reason.

Query a list of supported URI schemes and MIME types

    <method name="GetSupported">
      <annotation name="org.freedesktop.DBus.GLib.Async" value="true" />
      <arg type="as" name="uri_schemes" direction="out" />
      <arg type="as" name="mime_types" direction="out" />
    </method>

Get a list of all URI schemes and MIME types supported by the generic thumbnailer. This can be used by a consumer of the service to determine whether or not it makes sense to request the creation of a thumbnail for a specific file.

Returns:

  • uri_schemes: An array of URI schemes supported by the generic thumbnailer (e.g. ftp, file, http). Duplicate entries are possible (to allow combining positions with the mime_types array).

  • mime_types: An optional array of supported MIME types (e.g. image/png, image/jpg). If not empty, the array should have exactly the same size as uri_schemes. Each element in mime_types should correspond to the URI scheme with the same index in uri_schemes. As an example, the arrays file;ftp and image/png;image/jpeg mean that the thumbnailer supports file: URIs with the image/png MIME type and ftp: URIs with the image/jpeg MIME type.

Query a list of supported flavors

    <method name="GetFlavors">
      <annotation name="org.freedesktop.DBus.GLib.Async" value="true" />
      <arg type="as" name="flavors" direction="out" />
    </method>

Get a list of all supported flavors.

Returns:

  • flavors: An array of flavors supported by the generic thumbnailer (e.g. normal, large, special).

Query a list of supported schedulers

    <method name="GetSchedulers">
      <annotation name="org.freedesktop.DBus.GLib.Async" value="true" />
      <arg type="as" name="schedulers" direction="out" />
    </method>

Get a list of all schedulers supported by the generic thumbnailer. This can be used by a consumer of the service to hand pick a scheduler in the Queue method. Example values could be "foreground" and "background". The "default" scheduler will always be returned as first item in the array.

Returns:

  • shedulers: An array of schedulers supported by the generic thumbnailer (e.g. "foreground", "background" and "default").

  </interface>
</node> 

Thumbnailer manager

This thumbnailer manager interface is an optional part of this specification even though it is highly recommended to be implemented. It is used for runtime registration of specialized thumbnailers. It is usually implemented in the same process as the generic thumbnailer in order to enable delegation of thumbnailing work to specialized thumbnailers that have started after the generic thumbnailer.

The D-Bus service file

In order for the thumbnailer manager to be activatable over D-Bus, it is required to install a D-Bus service file. This file should have a unique name and should be versioned. An example filename for version 1 of an implementation called YourProject could be org.yourdomain.YourProject.Manager1.service. The format specified in the desktop entry specification is used to specify the D-Bus interface and the daemon executable. For version 1.x of this spec, this would be:

[D-BUS Service]
Name=org.freedesktop.thumbnails.Manager1
Exec=your-thumbnailer-or-managerd

Whether you want to append the version to the executable filename as well is up to you. Depending on how the specification is implemented, different versions of the spec could be implemented in the same daemon or in separate executables.

The service file needs to be installed into $XDG_DATA_DIRS/dbus-1/services/. Check out The basedir specification for more information about $XDG_DATA_DIRS. In a build environment that can use pkg-config use this command:

~$ pkg-config --variable session_bus_services_dir dbus-1
/usr/share/dbus-1/services
~$ 

org.freedesktop.thumbnails.Manager1

<?xml version="1.0" encoding="UTF-8"?>
<node name="/org/freedesktop/thumbnails/Manager1">
  <interface name="org.freedesktop.thumbnails.Manager1">  

Register a specialized thumbnailer dynamically

    <method name="Register">
      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
      <arg type="s" name="object_path" direction="in" />
      <arg type="as" name="uri_schemes" direction="in" />
      <arg type="as" name="mime_types" direction="in" />
    </method>

Register the caller as a specialized thumbnailer at runtime. Specialized thumbnailers do not have to be installed permanently (see Registering your thumbnailer below for more information about persistent registration of specialized thumbnailers). Specialized thumbnailers registered with Register are not remembered across multiple sessions. They are dropped when the manager service is shut down.

Parameters:

  • uri_schemes: An array of URI schemes supported by the specialized thumbnailer (e.g. ftp, file, http). Duplicate entries are possible (to allow combining positions with the mime_types array).

  • mime_types: An optional array of supported MIME types (e.g. image/png, image/jpg). If not empty, the array should have exactly the same size as uri_schemes. Each element in mime_types should correspond to the URI scheme with the same index in uri_schemes. As an example, the arrays file;ftp and image/png;image/jpeg mean that the thumbnailer supports file: URIs with the image/png MIME type and ftp: URIs with the image/jpeg MIME type.

  </interface>
</node>

Thumbnail cache

The thumbnail cache interface is an optional part of this specification even though it is highly recommended to be implemented. It is used to avoid regeneration of thumbnails when files are copied or moved and to clean up the cache sporadically or when a file is deleted.

The D-Bus service file

In order for the thumbnailer manager to be activatable over D-Bus, it is required to install a D-Bus service file. This file should have a unique name and should be versioned. An example filename for version 1 of an implementation called YourProject could be org.yourdomain.YourProject.Cache1.service. The format specified in the desktop entry specification is used to specify the D-Bus interface and the daemon executable. For version 1.x of this spec, this would be:

[D-BUS Service]
Name=org.freedesktop.thumbnails.Cache1
Exec=your-thumbnailer-or-manager-or-cached

Whether you want to append the version to the executable filename as well is up to you. Depending on how the specification is implemented, different versions of the spec could be implemented in the same daemon or in separate executables.

The service file needs to be installed into $XDG_DATA_DIRS/dbus-1/services/. Check out The basedir specification for more information about $XDG_DATA_DIRS. In a build environment that can use pkg-config use this command:

~$ pkg-config --variable session_bus_services_dir dbus-1
/usr/share/dbus-1/services
~$ 

org.freedesktop.thumbnails.Cache1

<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
         "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
 <node name="/org/freedesktop/thumbnails/Cache1">
  <interface name="org.freedesktop.thumbnails.Cache1">

Source files have moved

    <method name="Move">
      <arg type="as" name="from_uris" direction="in" />
      <arg type="as" name="to_uris" direction="in" />
    </method>

This method is called by the client to inform the thumbnailer that source files have been moved on the filesystem. File n in from_uris corresponds to the same n in to_uris. For example from_uris[20] got moved to to_uris[20] in case >= 20 files got moved. If only one file got moved, you only put one file in each array.

Parameters:

  • from_uris: the URIs that got moved

  • to_uris: the destination URIs to where from_uris got moved

Source files have been copied

    <method name="Copy">
      <arg type="as" name="from_uris" direction="in" />
      <arg type="as" name="to_uris" direction="in" />
    </method>

This method is called by the client to let the thumbnailer know about the copy of an array of source files. File n in from_uris corresponds to the same n in to_uris. For example from_uris[20] got copied to to_uris[20] in case >= 20 files got moved. If only one file got copied, you only put one file in each array.

Parameters:

  • from_uris: the URIs that got copied

  • to_uris: the destination URIs to where from_uris got copied

Source files have been deleted

    <method name="Delete">
      <arg type="as" name="uris" direction="in" />
    </method>

This method is called by the client to inform the thumbnailer about the deletion of an array of source files. If only one file got removed, you only put one file in the array.

Parameters:

  • uris: the URIs that got deleted

Cleaning up thumbnails

    <method name="Cleanup">
      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
      <arg type="as" name="uri_prefixes" direction="in" />
      <arg type="u" name="original_mtime_threshold" direction="in" />
    </method>

This method is called by the client to ask the thumbnailer to cleanup old or invalid thumbnails.

Parameters:

  • uri_prefixes: an array of base URIs. Thumbnails whose original URIs are descendants of any of these base URIs are to be removed.

  • original_mtime_threshold: filter so that only thumbnails of files that have a modified time older than original_mtime_threshold are deleted. Can be 0 to ignore the threshold and only cleanup based on the URI prefix array.

  </interface>
</node> 

Specialized thumbnailers

Specialized thumbnailers are additional thumbnailers the generic thumbnailer can use to delegate work to. While the generic thumbnailer can also generate thumbnails internally, specialized thumbnailers provide a way to have separate services running for creating thumbnails for certain URI schemes and/or MIME types. The generic thumbnailer is required to prioritize specialized thumbnailers over internal implementations. This allows for proprietary thumbnailers and thumbnailers written by the community to extend the thumbnailer functionality.

Service name of a specialized thumbnailer

The service name of specialized thumbnailers is the location where they live on the D-Bus session bus. The rule for service names is to use your internet domain name with its elements reversed. For example, an organization with an internet domain name company.com would name its thumbnailer service com.company.Thumbnailer1 and the object path on the bus would be named /com/company/Thumbnailer1. Specialized thumbnailers have to implement the org.freedesktop.thumbnails.SpecializedThumbnailer1.

There are two ways to register a specialized thumbnailer with the generic thumbnailer. See Registering a specialized thumbnailer for more information about this.

org.freedesktop.thumbnails.SpecializedThumbnailer1

Generating thumbnails with the `Queue` method

Specialized thumbnailers must provide a Queue D-Bus method. It is used by the generic thumbnailer to delegate the creation of a thumbnail to a specialized thumbnailer. The Queue method is called to in order to generate a thumbnail for a single URI. It is expected to emit either a single Ready or Error signal, depending on the success of the operation. The Ready signal must be emitted as soon as the thumbnail has been created and saved as specified in the thumbnail managing standard on a typical platform. If for some reason the thumbnail cannot be generated, the Error signal has to be emitted as soon as possible. The generic thumbnail is reponsible to propagate this error to thumbnailer clients.

Only URIs with URI scheme and MIME type supported by the specialized thumbnailer will be passed to the Queue method. For more information about defining the supported URI schemes and MIME types see Registering a specialized thumbnailer.

It is up to the specialized thumbnailer to determine whether thumbnails have to be generated or can be reused in case they already exist.

The Queue method must return immediately. To propagate that a thumbnail is ready, use the Ready signal. To propagate an error, use the Error signal. Don't block Queue until the tumbnail is ready. There is no restriction as to when Queue may be called on your specialized thumbnailer service. It is the responsibility of specializd thumbnailers to queue and process parallel requests made with Queue.

Example with service name as com.company.Thumbnailer1:

<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
         "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
 <node name="/com/company/Thumbnailer1">
  <interface name="org.freedesktop.thumbnails.SpecializedThumbnailer1">  

Request to create a thumbnail

    <method name="Queue">
      <arg type="s" name="uri" direction="in" />
      <arg type="s" name="mime_type" direction="in" />
      <arg type="s" name="flavor" direction="in" />
      <arg type="b" name="urgent" direction="in" />
      <arg type="u" name="handle" direction="out" />
    </method>

The parameters that will be passed to Create are:

  • uri: A URI to generate the thumbnail for. For example `uri = "file:///home/user/image1.jpeg".

  • mime_type: The MIME type of the uri. In the above example this would be "image/jpeg".

  • flavor: The flavor that should be made (eg. normal).

  • urgent: Whether this is a request that should be solved urgently (usually will "foreground" schedulers set this)

This method always returns a handle different than 0. The returned handle can be used in a Dequeue request.

Cancel/Dequeue thumbnail requests

    <method name="Dequeue">
      <arg type="u" name="handle" direction="in" />
    </method>

The Dequeue method removes thumbnail requests for specialized thumbnailer from its queue. A specialized thumbnailer doesn't have to guaranteed that any requests will be canceled as a result of this call. A specialized thumbnailer may cancel an in-progress request if possible, but clients should not depend on this behavior being available. Although it's recommended that the specialized thumbnailer won't do this, a queued request that is dequeued can still cause Ready and Error signals to be emitted before the Finished signal. The Started and Finished signals will always be emitted (for all dequeued items).

Parameters:

  • handle: The handle that got returned to you from an earlier Queue call.

Thumbnail is ready for use

    <signal name="Ready">
      <arg type="u" name="handle" />
      <arg type="s" name="uri" />
    </signal>

Emitted when thumbnail was generated and saved on disk successfully. Every URI that is processed without errors must be reported back to the generic thumbnailer using this signal.

Parameters being passed to you:

  • handle: The handle that was returned to you from an earlier Queue call.

  • uri: The uri is the URI of the file for which the thumbnail was generated. In order to locate the actual thumbnail on a typical platform, use the thumbnail managing standard.

Enqueued request is started to be processed

    <signal name="Started">
      <arg type="u" name="handle" />
    </signal>

This signal is emitted when an enqueued request is started to be processed. Started and Finished will be emitted for all requests that were made via the Queue method before the first and after the last URI of a request is or was processed. This also includes requests that failed entirely because none of its URIs or MIME types are supported. It's possible that the specialized thumbnailer uses dbus_message_set_destination for emits of this signal (set to the sender of the Queue method). Started will be emitted only once for each Queue call.

Parameters being passed to you:

  • handle: The handle that was returned to you from an earlier Queue call.

Enqueued request is completed

    <signal name="Finished">
      <arg type="u" name="handle" />
    </signal>

Emitted when a request queued earlier with the Queue method has been completed. This is the case when all URIs that were part of the request have been processed. It is irrelevant whether they succeeded or not. Started and Finished must emitted in any case before the first and after the last URI of a request is or was processed. It's possible that the specialized thumbnailer uses dbus_message_set_destination for emits of this signal (set to the sender of the Queue method). The Finished signal will be emitted only once for each Queue call. If Finished is emitted but not all uris of the Queue were reported back to the client via an Error or Ready signal, then this means that the request was dequeued. As dequeuing may happen at any time, clients have to make sure to handle this scenario appropriately.

Parameters being passed to you:

  • handle: The handle that was returned to you from an earlier Queue call.

Error occured

    <signal name="Error">
      <arg type="u" name="handle" />
      <arg type="s" name="failed_uri" />
      <arg type="i" name="error_code" />
      <arg type="s" name="message" />
    </signal>

Emitted when the thumbnail for a file could not be generated due to an error. The Error signal has to be propagated to thumbnailer clients by the generic thumbnailer.

Parameters being passed to you:

  • handle: The handle that was returned to you from an earlier Queue call.

  • failed_uri: The URI for which the thumbnail generation failed.

  • error_code: An error code describing the type of the error. See the Error signal of the generic thumbnailer for the error codes defined in this specification.

  • message: Additional textual information about the error, like a detailed description of its reason.

  </interface>
</node> 

Registering a specialized thumbnailer

There are two ways to register a specialized thumbnailer:

The first way is to use the org.freedesktop.thumbnails.Manager1 interface described earlier in this specification. This of course does not register the specialized thumbnailer permanently and thus, is often not powerful enough. Whenever the manager service is shut down, all specialized thumbnailers registered at runtime are dropped.

The second way, which also registers a specialized thumbnailer permanently, is to install a D-Bus service file and a thumbnailer description file into the system.

The com.company.Thumbnailer1.service file

The service file enables on-demand activation of the specialized thumbnailer over D-Bus. All specialized thumbnailers installed permanently are required to installed this file.

Example file: $XDG_DATA_DIRS/dbus-1/services/com.company.Thumbnailer1.service

[D-BUS Service]
Name=com.company.Thumbnailer1
Exec=/opt/company/thumbnailer/libexec/thumbnailerd

The file has to be installed into $XDG_DATA_DIRS/dbus-1/services/. Check out the basedir specification for more information about $XDG_DATA_DIRS. In a build environment that can use pkg-config use this command:

~$ pkg-config --variable session_bus_services_dir dbus-1
/usr/share/dbus-1/services
~$ 

The thumbnailer description file

The thumbnailer description file makes it possible for the generic thumbnailer to find registered specialized thumbnailers at startup. They are then activated and connected to, so that they can be used to delegate thumbnailing work later.

Example: $XDG_DATA_DIRS/thumbnailers/com.company.Thumbnailer1.service

[Specialized Thumbnailer]
Name=com.company.Thumbnailer1
ObjectPath=/com/company/Thumbnailer1
UriSchemes=file;file;ftp;sftp
MimeTypes=image/png;image/jpeg;image/png;image/png
Comment=free comment

Required fields:

  • Name: The D-Bus bus name of the thumbnailer.

  • ObjectPath: The D-Bus object path used for the thumbnailer.

  • MimeTypes: A list of all MIME types supported by the specialized thumbnailer.

Optional fields:

  • UriSchemes: List of all URI schemes supported by the specialized thumbnailer. If this field is ommitted then the default value is file.

  • Comment: Optional description that can be used for things like a copyright notice.

This file has to be installed into $XDG_DATA_HOME/thumbnailers/. Check out The basedir specification for more information about $XDG_DATA_DIRS and $XDG_DATA_HOME.

To install this file in a autotools build environment, you can use something like this in a Makefile.am:

thumbnailersdir = /usr/share/thumbnailers
thumbnailers_DATA = com.company.Thumbnailer.service

Conflict resolution

Multiple specialized thumbnailers may end up supporting the same URI schemes and MIME types. A conflict occurs only when two thumbnailers support at least one identical URI scheme and MIME type pair.

The sample below illustrates a file URI conflict for image/jpeg and image/xpm between com.X.Thumbnailer1 and com.Y.Thumbnailer1.

$XDG_DATA_DIRS/thumbnailers/com.X.Thumbnailer1.service

[Specialized Thumbnailer]
Name=com.X.Thumbnailer1
ObjectPath=/com/X/Thumbnailer1
MimeTypes=image/png;image/jpeg;image/xpm
UriSchemes=file;ftp;ftps;http;https;nfs;smb

$XDG_DATA_DIRS/thumbnailers/com.Y.Thumbnailer1.service

[Specialized Thumbnailer]
Name=com.Y.Thumbnailer1
ObjectPath=/com/Y/Thumbnailer1
MimeTypes=image/jpeg;image/xpm
UriSchemes=file

In order to handle conflicts in specialized thumbnailers the generic thumbnailer is required to give priority to more recently registered or installed thumbnailers over older thumbnailers. For dynamically registered thumbnailers the timestamp of the Register call has to be used. For specialized thumbnailers registered permanently, as described above, the generic thumbnailer is required to use the modification time of the thumbnailer description files in $XDG_DATA_DIRS/thumbnailers/. On top of that, thumbnailers with descriptions installed to $XDG_DATA_HOME/thumbnailers have priority over files in $XDG_DATA_DIRS/thumbnailers.

You can override this decision by providing a $XDG_DATA_DIRS/thumbnailers/overrides or $XDG_DATA_HOME/thumbnailers/overrides file (with the latter overwriting the former in case both exist). This file looks like this:

Example: $XDG_DATA_DIRS/thumbnailers/overrides (giving priority to com.Y.Thumbnailer1 over com.X.Thumbnailer1)

[file-image/jpeg]
Name=com.Y.Thumbnailer1
ObjectPath=/com/Y/Thumbnailer1
UriScheme=file
MimeType=image/jpeg

[file-image/xpm]
Name=com.Y.Thumbnailer1
ObjectPath=/com/Y/Thumbnailer1
UriScheme=file
MimeType=image/xpm

Format of the overrides file:

  • section name: Is formed by concatenating the URI scheme together with a dash and the MIME type. For each combination to be overriden, a new section has to be defined.

  • Name: The D-Bus bus name of the preferred thumbnailer.

  • ObjectPath: The D-Bus object path of the preferred thumbnailer.

  • UriScheme: The URI scheme used in the section name.

  • MimeType: The MIME type used in the section name.

The purpose behind the overrides file is that very efficient thumbnailers (com.Y.Thumbnailer1 in the example) can be given priority over all other thumbnailers supporting the specified URI scheme and MIME type pair. In the example, com.X.Thumbnailer1 could be a less efficient thumbnailer which is implicitely given lower priority for file URIs but is still going to be used for the remote filesystems it supports (e.g. http and ftp).

A more concrete example would be a specialized thumbnailer that uses a library like EPeg. At the moment of writing EPeg does not support VFS layers like KIO or GIO and thus, can only handle local JPEG files. Another specalized thumbnailer able to handle remote files as well (like a GdkPixbuf thumbnailer that uses a GInputStream and a GFile to read its input files) might be installed or register later. Due to the performance gain with EPeg you might want to use the EPeg thumbnailer for local files. For remote files you want the GdkPixbuf thumbnailer to be used.

Implementation recommendations

Asynchronous handling and prioritizing

It's strongly recommended for implementers of the generic thumbnailer to make schedulers for "foreground" and for "background" priorities. The "foreground" should for example be a LIFO scheduler. The "background" can for example be a normal FIFO but with I/O and scheduler priorities set to IDLE.

For a "foreground" scheduler it's strongly recommended not to group Ready and Error signals together. Whereas for a "background" scheduler this is recommended.

It's recommended to stop sending Ready and Error signals for a queued task as soon as its Dequeue takes place. You can indeed immediately call Finished, the client must handle missing Error or Ready signals (you can safely assume that the client must count it by itself).

Unmount events of removable devices

It's recommended to detect the mount-pre-unmount event of drives and removable devices and to either Dequeue entire queued tasks that contain uris pointing to resources on the device being mounted, or to cancel individual uris within the task (just call Finished and forget about the canceled ones, the client must handle this by itself). For mobile devices this is a strong recommendation, else the user might end up in the situation where he has to wait for a large queue of thumbnails to be made before he can unplug his removable devices.

Specialized thumbnailer's registrations

As the generic thumbnailer is responsible for calling Queue methods on specialized thumbnailers based on a registration of a MIME type (see above), it's recommended (but not required) to use a file notification monitor in $XDG_DATA_DIRS/thumbnailers and $XDG_DATA_HOME/thumbnailers to detect the registration of a new specialized thumbnailer.

Another (less optimal) possibility is to restart and reinitialize your generic thumbnailer each time a specialized thumbnailer is installed. This is a solution for distributions and packagers dealing with a thumbnailer implementation that wont automatically pick up new specialized thumbnailers.

Yet another possibility is to check for newly installed specialized thumbnailers at the start of each request in the queue (see the Queue method above). If any new ones got installed, take them into account (and add the registration to your register).

Obviously, these are just recommendations. As an implementer, it's up to you to optimize this for your implementation's purposes.

Resource usage, shutting down after timeout

As mentioned above, we require you to install a .service file in $XDG_DATA_DIRS/dbus-1/services. This means that we require your generic thumbnailer to be activatable. Therefore it's allowed, if your implementation permits it, to shutdown the daemon (if implemented as a daemon) after a period of inactivity.

The amount of inactive time required before you shutdown is unspecified and up to you. It is recommended to pick a value that is more than a minute after the last queued request was finished. Such a timeout avoids that the daemon (again, if implemented as a daemon) has to be launched often.

Strongly note that it's not required to shutdown, but strongerly note that it's required to be activatable.

DraftSpecs/ThumbnailerSpec (last edited 2013-12-02 17:52:58 by WilliamJonMcCann)