This is

as days pass by, by Stuart Langridge

. Here I write about many things. In the past I wrote about other things but the past is past. I write code for people to play with, I write about my life on Twitter, and I write here.

On I wrote An Ubuntu One printer, on the subject of Ubuntu One, u1adp, printers, HOWTOs, and u1.

At the Ubuntu Developer Summit in October 2011 there was a session on Ubuntu One cloud printing. That session was about Ubuntu One being a gateway to existing cloud printing services, like HP's ePrint and Google Cloud Print, and I'm looking into that. However, the idea of Ubuntu One being itself a cloud printing service came up in that discussion: specifically, if I've got an Ubuntu machine with a printer plugged into it, can I make that printer available from other machines (or other devices such as phones) through Ubuntu One itself? Can I take my home printer and use Ubuntu One to set it up so that I can print to that printer from anywhere in the world and from any device? We (the U1 team) won't be working on that idea directly, but in the session I suggested that it would be relatively easily done. Some people asked how it could be done, and suggested that they might be interested in working on it. This describes one way to do it.

Basically, this process involves being able to send documents to the machine with the printer connected to it, and then having that machine notice the newly-arrived documents and printing them. To do this, we need a "U1 printer daemon" on the printer machine. I propose the following architecture:

There is a machine, in your house or similar, with a printer connected to it. We'll call this machine the printer machine. On the printer machine, set up the printer so it can be printed to locally. Next, we invent a printer daemon. This printer daemon creates a folder and marks that folder as synced with Ubuntu One, and subscribes to that folder on this machine. The printer daemon then waits for new files in that folder (see below for how to do this). When a new file arrives, the printer daemon sends the file to the local printer, and then deletes the file (so it doesn't linger around forever).

I suggest that the folder that's creates is named $HOME/.ubuntuone/Print Queues/printer name. It's a hidden folder because it's not really something that should be shown in a user's home folder; it's under .ubuntuone because that's a static path across machines (putting it in $XDG_DATA_HOME is problematic because that path may not be the same on all machines), it's a separate synced folder (rather than being under $HOME/Ubuntu One) because files for printer A only need to be synced to the machine connected to printer A, not to all machines you have connected to Ubuntu One, and it's under .ubuntuone/Print Queues because third party apps which want to offer "print to an Ubuntu One printer" can then list all your Ubuntu One printers by enumerating the contents of that folder via the REST API.

A third-party app (say, one on a mobile phone) which wants to offer "print to an Ubuntu One printer" would then take the document to be printed, show the user the collection of Ubuntu One printers (by enumerating the contents of .ubuntuone/Print Queues using the REST API) and then upload the document to be printed to the chosen .ubuntuone/Print Queues/printer name folder. No-one ever sees the existence of the .ubuntuone/Print Queues folder, of course; it's all transparent to the user.

Now, how does one monitor an Ubuntu One synced folder for changes? If you're a Python app (on Ubuntu or Windows) and you're running a very recent build of Ubuntu One (the shortly-to-be-released Windows build, or a nightly build on Ubuntu) you can use the Python SyncDaemonTool, and your daemon would look roughly like this:

import os, sys

if sys.platform != 'win32':
    from twisted.internet import glib2reactor
    glib2reactor.install()
    from dbus.mainloop.glib import DBusGMainLoop
    DBusGMainLoop(set_as_default=True)

from twisted.internet import defer, reactor
from ubuntuone.platform.tools import SyncDaemonTool
EXPECTED = os.path.expanduser('~/.ubuntuone/Print Queues/')

@defer.inlineCallbacks
def track_file_download():
    sd = SyncDaemonTool()
    success_filter = lambda path, info: path.startswith(EXPECTED)
    path, info = yield sd.wait_for_signals(signal_ok='DownloadFinished',
                                           success_filter=success_filter)
    print '==========\n', path, info

if __name__ == '__main__':
    reactor.callWhenRunning(track_file_download)
    reactor.run()

This, as noted, requires a very very recent build of Ubuntu One, so it's probably not useful right now (it will be in the future, though, so if you're reading this as a result of a Google search, do it this way). The other way to do this on Ubuntu is to listen to the DownloadFinished signal on the com.ubuntuone.SyncDaemon.Status D-Bus interface: that code would look something like this:

import dbus, gobject
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
def track_file_download(path, info):
    print path
dbus.SessionBus().add_signal_receiver(handler_function=track_file_download,
    signal_name="DownloadFinished", 
    dbus_interface="com.ubuntuone.SyncDaemon.Status",
    bus_name="com.ubuntuone.SyncDaemon", path="/status")
loop = gobject.MainLoop()
loop.run()

A note: most files can't be printed as is: they need the application that generated them to print them. However, printing systems know natively how to handle PDF files. What this means, in practice, is that the app which uploads the file for printing to the printer queue folder should convert it to PDF before uploading it.

That's my proposal for how this could be done. If you're interested in hacking on this, I'd love to hear from you!

Tony Whitmore

Some sort of location meta-data for the printer would be useful, especially if you have access to more than one printer of the same model.

sil

Tony: a good point and well argued. That seems like a reasonable thing to add (name the folder "HP Deskjet - study" or something...)

Corey Burger

Just a minor nitpick, because I love the idea, FHS?

Also, the print dialog should make it clear which are local printers and which are cloud printers, so I don't end up printing to home while at work, or vice-versa.

Mark Fraser

Would it be possible to have this running as a service on a server so that you didn't even need your computer running in order to print?

Michał Sawicz

One more thing - the printer queue folder should contain a metadata file that would describe its capabilities like duplex or paper source.

sil

Corey: yeah; the problem with using the FHS here (that is: using XDG folders) is that they may differ from machine to machine. (My XDG_DATA_HOME is ~/Applications/Data for example, not ~/.local/share.) As for the print dialog... true, although I hadn't really thought about making cloud printers available *from* an Ubuntu machine; the assumption is that if you're connected to a printer then you'll print to it, and this is for mobiles or laptops that have access to the net but don't have a printer, because if you want to print to your LAN then we already handle that well. Perhaps not a valid assumption :)

Mark Fraser: yep, this should be possible; Ubuntu One can run headless, if you set it up right.

Michał: for version 2 of this, yeah, I can see that; my initial thought was a quick way to print a document while on the run, but adding more complexity in order to make printing more powerful seems a good idea in the long run!

oliver

How does this compare to using CUPS (IPP?) for printing?

I guess an U1 printer would be a "light" solution which can be accessed from any device which has U1 file sharing client and supports PDF creation; on the other hand, CUPS requires a different client but also offers more features (detailed printer description, job status etc.).

sil

oliver: the flaw with IPP is that from the internet I can't see my printer, and I don't want to have to punch a port through my firewall and expose the printer to the whole internet. Certainly that'd *work*, but it's harder to set up and more dangerous security-wise.

Aidan Delaney

Sil,

I'm still at a loss to understand *why* I want to use any cloud print service. I particularly don't get why I'd want to print from a location where I can't pick up the printed stuff. Could you explain some of the use-cases for this?

sil

Aidan: one of my main ones is printing boarding passes; I quite often find myself in the pub the night before I fly and think "ah, man, I should check in now or I'll get some horrible middle seat". So I check in from my phone, and then... download the boarding pass as a PDF and then email it to myself, and then when I get home I have to remember to grab it back out of my mailbox and print it. (Yes, PDF on the phone itself and no paper, but... not on most airlines :)) My use cases all revolve around (a) sometimes I have to print stuff and (b) I do about half my net stuff from my phone while I'm out and about, these days.

This website belongs to Stuart Langridge. Contact details are available. Don't eat yellow snow. Valid HTML5, at least in theory, except for the bits that aren't because I'm that futuristic that I'm ahead of the spec, oh yes. HTML5 help from Bruce Lawson, among others. Fonts from the superb FontSquirrel. End.