RECAP
In case you don’t remember, our project is to make the scripting environment MediaScheme compatible with the vector-editing program Inkscape. This will allow us (and anyone else) to write Scheme commands to generate images in Inkscape. The main hurdle in this project is finding a way for MediaScheme and Inkscape to interact. To do this we are using something called D-Bus.
WHAT IS D-BUS?
D-Bus is an inter-process communication system. This means that D-Bus works as a middleman, allowing different applications running on one computer to communicate with one another. D-Bus enables this communication through the exchange of messages.
D-Bus Components
Two of the most important things that make D-Bus work are the D-Bus library and the message bus. The D-Bus library is known as libdus. It is what allows applications to connect and exchange messages. The message bus is what applications actually connect to. It receives a message from the sending application and routes it to the receiving application(s) appropriately.
Buses
D-Bus uses two types of buses, a system bus and a session bus. The system bus is for system-wide communication. It might be used for something like notifying users that new hardware has been installed to the system. Alternatively, a session bus is specific to an individual user of the system. A session bus allows communication only between applications running within each user’s own session, not between sessions of different users. Since we want MediaScheme to communicate with a user’s specific instance of Inkscape, independent of what other users might be doing with Inkscape, we will be working with the session bus.
Objects
In D-Bus, clients are applications that send messages on the bus with requests for other applications. The applications that receive these messages are called services. A service has one or more objects on which methods sent from the client application can be invoked. In the case of D-Bus, there are two objects: the Application object and the Desktop object. Methods that use the Inkscape service but are independent of any particular Inkscape document are invoked on the Application object. Opening a new document is an example of such a method. Methods that function within the context of a specific Inkscape document are invoked upon the Desktop object. Changing the color of a specific circle in a specific image would be an example of such a method. Objects are identified by paths stored in reverse-domain name format. There is only one Application object, identified by /org/inkscape/application. There can be as many Desktop objects as there are Inkscape documents open at one time. Desktop objects are identified by the path /org/inkscape/desktop_#, with # being a number unique to each individual object (and therefore to each individual document).
Messages
Messages carry the information that an application wants to communicate and are comprised of a header and a body. The header contains fields with information such as the sending and receiving bus names, the name of any methods the message carries, and data types contained in the message body. This information ensures that the message reaches its intended destination and not a different service. The message body contains the arguments that will be used to call the requested method once the appropriate destination is reached.
There are four types of messages:
- Method Call
Client process sends a request for a method to be invoked on an object - Method Return
Object returns the results to the client process after the message has been invoked - Error
Returns an error message if the method fails - Signal
Indicates to all applications that a signal has been emitted for interested applications to use
For the sake of connecting MediaScheme and Inkscape, we will not be working with signals.
Proxies
A proxy object enables messages to reach the service object. It does this by serving as a “stand-in” object for the service object. The proxy object receives the method call and interprets it so that it can be used on the service object. After the method is invoked, the service object passes any return values back to the proxy object which then sends the values in the return call. Using a proxy is what allows applications written in different languages to communicate. For this project we have written proxy bindings that allow us to write function calls in C that call methods in Inkscape using Python. Eventually, we hope to use MediaScheme functions to call methods in Inkscape.
WHY D-BUS?
A project similar to ours was implemented a few years ago. This project was called “SchemeInk.” One of the authors of this project, Soren Berg, went to work on a Google Summer of Code project to make Inkscape scriptable. He did this through D-Bus. With D-Bus, users can call commands that use the capabilities of Inkscape to create images. There are commands for common actions such as cutting and pasting, making rectangles, ellipses, and other objects, moving, scaling, and rotating objects, etc. Since there was this pre-existing API for scripting Inkscape with a design clearly suited toward inter-process communication, we felt that making Inkscape compatible with Media-Scheme would be best achieved by extending the current Inkscape/D-Bus scripting API.
SOURCES
IntroductionToDBus
D-Bus Tutorial
Meego
Proxy Objects
Why Scheme? How many people heard of MediaScheme? How many docs or libraries are out there for Scheme compared to more popular scripting languages?
Why don’t you use JavaScript or Lua for scripting? Both are very popular and wildly adopted. That’s what Maya guys realized with MEL when they added Python support, and Adobe when they added JavaScript support to their products. Do the right thing from the start. Don’t go the GIMP path which is so much inferior usability wise than Inkscape.
Some good questions. Here’s a partial answer: We’re starting with Scheme because we like Scheme. Unlike JavaScript or Lua, Scheme is clean and elegant. (Well, R5RS Scheme is clean and elegant.) We’re also doing this in an academic setting, and we use Scheme as our introductory language. But Python is next on the list. We’ll see about JavaScript or Lua.
A context note that the K’s may not have mentioned (at least not in this post). Our target is really interactive scripting, in which the programmer is experimenting. (So, lots and lots of one-liners to see the results.) In my experience, JavaScript is rarely used in interactive scripting environments. I’m less sure about Lua. In contrast, Scheme and Python are regularly used for interactive scripting.
Of course, the D-Bus support that is now in Inkscape means that any language can potentially script it. That’s why that was the first step (and why the Inkscape folks supported a GSoC project).
Thank you for explaining.