Presenter software for pdfs

When it comes to presenting on a Linux PC, the powerpoint format is not an option. Neither is Openoffice/Libreoffice for me. Designing presentations with Openoffice/Libreoffice can be quite frustrating and results in incompatibilities with other presentation slide generators like Powerpoint.

The only format that can guarantee consistency of your presentation across devices is pdf.

When you want to present a pdf, you can just open it in any pdf viewer, go fullscreen and mirror the display. But this simple setup is still far away from the comfort of Libreoffice/Openoffice/Powerpoint presentation mode. Wouldn’t it be nice to combine the reliability of pdf with the flexibility of the presentation mode found in Libreoffice/Openoffice/Powerpoint?

My requirements for a pdf presenter software are as follows:

-An extended desktop setup, with one screen showing the current  slide and the oder screen showing a preview of the upcoming slides.

-Be able to show notes and annotations that are not visible on the main screen. Notes should be easy to modify.

-Easy navigation between the slides and an overview of the complete presentation with slide thumbnails.

There seem to be very few pieces of software out there that support those concepts. One that fits my needs is https://pdfpc.github.io/ .

The notes are written to a plaintext file and can be edited inside the application while in presentation mode or with any text editor.

It comes with many useful features that can be found on the home page and which I will not reiterate here.

The weak spots of pdfpc are in my opinion:

-Initial rendering of the thumbnails can take some time

-Escape ends the presentation, escape also exits annotation mode. Visually it is not always clear if annotation mode is still running and you might unintentionally end your presentation.

Apart from that it is a very good presenter software that I can fully recommend to anyone doing presentations in pdf format.

Advertisements

Wireless scanning with Canon PIXMA on Linux – timeout issues ( solved )

Canon devices have their own USB over IP protocol for communicating wirelessly. This allows users to scan and print with Canon devices without physically connecting them.

Arch users would install aur/cups-bjnp and then configure the device in cups.

Printing with cups works nicely out of the box, but I had timeout issues with scanning. Nine out of ten times the scan would not finish successfully, but abort with an error message complaining about a timeout.

The solution for this is quite easy: set a high timeout value in /etc/sane.d/pixma.conf, something like 5s.

bjnp-timeout=5000

After setting this value, timeout errors during scans disappeared entirely.

Awesome Window Manager – Maximization issues

I have been a convinced follower of this tiling window manager [link] for some years, and never ever dream of going back to the messy days of stacking window managers.

Recently, I noticed that some windows start maximized like firefox or chrome ( with a + symbol in the taskbar ), and I’m unable to de-maximize them with conventional keybindings. The ordinary way for toggling maximization ( Mod4 + m ) does not change them in any way, and it results in different flags on the taskbar that indicate vertical and horizontal maximization.

After some fiddling I discovered that at least 3 ways exist to maximize a window and the default keybinding does not deal windows that are just maximized ( and thus different from vertically and horizontally maximized windows ). Here are the taskbar glyphs for each of them.

+ maximized
maximized_horizontal
maximized_vertical

A simple new keybinding to unset all three maximization flags for a given client can easily solve this when added to rc.lua :

awful.key({ modkey, “Shift” }, “m”,
function (c)
c.maximized = false
c.maximized_vertical=false
c.maximized_horizontal=false
c:raise()
end ,
{description = “demaximize”, group = “client”})

 

Mod4 + shift + m will cut all client windows down to size now

Random thought of the day

“Be silent and listen: have you recognized your madness and do you admit it? Have you noticed that all your foundations are completely mired in madness? Do you not want to recognize your madness and welcome it in a friendly manner? You wanted to accept everything. So accept madness too. Let the light of your madness shine, and it will suddenly dawn on you. Madness is not to be despised and not to be feared, but instead you should give it life…If you want to find paths, you should also not spurn madness, since it makes up such a great part of your nature…Be glad that you can recognize it, for you will thus avoid becoming its victim. Madness is a special form of the spirit and clings to all teachings and philosophies, but even more to daily life, since life itself is full of craziness and at bottom utterly illogical. Man strives toward reason only so that he can make rules for himself. Life itself has no rules. That is its mystery and its unknown law. What you call knowledge is an attempt to impose something comprehensible on life.”

-CG Jung, The Red Book

Firefox and dark GTK themes

Dark GTK themes can look very strange in firefox, since input widgets are likely to get transformed into dark pits with dark background colors and equally dark foreground fonts. Fortunately there is at least one solution that does not require fiddling around with GTK theme definitions.

The firefox plugin “Stylish” allows you to define your custom style overrides in css for your firefox browser.

https://addons.mozilla.org/en-US/firefox/addon/stylish/

To fix input widget color you would create a new style and copy something like the following into the style definition (sorry for the messy indentations caused by copy-pasting). Voilà, no more black holes in your browser sucking in your input text.

@-moz-document url-prefix(http), url-prefix(file) {
pre, input, textarea {
 color: black !important;
 background: white !important;
 border-left-color: gray !important;
 border-right-color: gray !important;
 border-top-color: gray !important;
 border-bottom-color: gray !important;
}
input:not([type="button"]):not([type="checkbox"])
:not([type="submit"]):not([type="reset"]), 
select {
 color: black !important;
 background: white !important;
 border-left-color: gray !important;
 border-right-color: gray !important;
 border-top-color: gray !important;
 border-bottom-color: gray !important;
}
}

Quote of the day

The dynamic principle of fantasy is play, a characteristic also of the child, and as such it appears inconsistent with the principle of serious work. But without this playing with fantasy no creative work has ever yet come to birth. The debt we owe to the play of imagination is incalculable. It is therefore short-sighted to treat fantasy, on account of its risky or unacceptable nature, as a thing of little worth. – CG Jung, Psychological Types

Random deep thought of the day

“What strikes me is the fact that in our society, art has become something which is related only to objects and not to individuals, or to life. That art is something which is specialized or which is done by experts who are artists. But couldn’t everyone’s life become a work of art? Why should the lamp or the house be an art object, but not our life?” – Michel Foucault

Learning a foreign language

One of the advantages of not being a native speaker of this wonderful mess existing under the umbrella term of ‘English language’ is that you will truly appreciate things like the following:

Waterfall is the opposite of firefly.

Seems legit to me.

The most interesting variant of this pluricentric language is definitely Engrish. And it is somewhat a secret language, since you cannot find courses or books for it. It has no semantic or syntactical rules, but relies entirely on intuition and creativity. This miracle language has recently gained popularity in eastern Asia.

engrish-lol28Engrish_44fa87_299912

189597d9d8968e05fe727368ee92df82

 

Have chinchillas been giving you nightmares lately? If you do not associate chinchillas with cuddly rodents, but orthographic nightmares, chances are high that you are a student of the Russian language. This is the word шиншилла in russian cursive script:

1426002913_1004627246

 

If your hovercraft is still not full of eels yet, try German ( not a foreign language to me, so I might be somewhat biased ) :

long_german_words

Oh, come on, it’s just an elementary word. Read some fiscal laws for some mindblowing experience and you will end up learning Italian which is basically a collection of loosely coupled vowels.

Have fun learning languages!

 

Inkjet printer woes

WhatsApp Image 2017-06-13 at 20.17.21

What a wonderful contraption is an inkjet printer! Countless different models of so many manufacturers are out there, only to be constantly superseded by new models with new innovations, such as new number or letter suffixes for the name. A new suffix for the printer model can decide between flawless driver integration and driver selection hell, when you try to match the printer’s name to the available driver out of 10^6 options.

If you let these things autoinstall the software they come packaged with, be prepared for a big ball of mud that will drain your system’s resources after installing all the things they throw at you, none of which are actually required for printing.

And this is only scratching the surface. Continue reading at your own risk, but think well before, if you can stomach it.

Inkjet printers depend on a mythological substance that would have been probably praised by medieval alchemists for its elusive qualities. Printer ink. On a metaphysical level, curses are the second, intangible ingredient for operating a printer, but at least they don’t strain your budget ( unless the penal code of your country implements fines for cursing ), and therefore will not be covered here. With printer ink, you are not that lucky.

Ink cartridges are sometimes more expensive than the printer. And it leaves one wondering where all the CMYK and black ink vanishes to. Internet lore even tells us about printers accumulating black goo somewhere on the inside just to trick the customer into buying new cartridges. Since many printers clean their nozzles by flooding them with ink, the story cannot be dismissed entirely as a legend. Even the alien trilogy has picked up the subject of black goo, where fittingly everybody who touches the black goo is turned into a mutant. A subtle warning against disassembling your printer perhaps? Disclaimer: I have not witnessed any cases of mutation yet, only tears and curses over the wasted ink so far.

And nobody knows why printers can be huge and have really tiny cartridges. The HP Deskjet 4100 on the bottom of the printer stack in the picture is huge, its cartridges are tiny and its hunger for ink inexhaustible. Also these cartridges have the printing head attached to them, to make them more expensive and harder to refill or replace with imitation products.

Let us take a look at the lifespan of the average inkjet printer. Once they are in use, they are required to exercise their printing prowess every few months or dry up. If the ink dries up inside the printing head, all that will be left is a big hunk of garbage.

Happened to me with the second printer in the row, the Canon Pixma IP4200. I tried cleaning it with alcohol, but the only result was that my hands looked like Van Gogh’s after a psychotic painting seizure.

Regardless of what I do, black PGBK does not print even a dot. This problem occurs so often and forums on the net are filled with it, that many have used the word planned obsolescence to explain its frequent emergence.

What can you do with an old printer? Absolutely nothing. People will not even take it, if you offer it for free. If you are the flowery kind of person you can remove the printer’s innards and plant some flowers inside. Or if you are lucky enough to have ample storage space, you can cram your old printers in there and offer them to posterity some decades later as dreadful artefacts from the past that drove people crazy.

My advice on inkjet printers:

-try to avoid them

-if you can’t, get one with cartridges that come without electronic circuitry attached to them. They are cheaper to refill.

-buy an all-in-one thing that can also scan and copy. It will safe you some space.

 

 

 

Building a CalDAV interface – Request and Response example

A couple of months ago, I was tasked with building a CalDAV interface for calendar synchronization with an existing, but highly customized webserver with an existing calendar application from scratch. An impressive number of implementations already exist, most in the open source spectrum. But what I could not find was a step by step guide covering the whole communication from discovery to item delivery. Studying the sources is very insightful, though not very efficient. Reading the convoluted rfcs deprecating each other is even worse. So here is my attempt at a basic, language-agnostic guide.

CalDAV uses the standard http methods like GET and PUT, inherits some from DAV, like PROPFIND and defines also its own like REPORT. Let’s take a closer look at the main request types.

OPTIONS

This request is wonderfully simple. The server returns the supported subset of CalDAV functionality in the header and sends it to the client with http status 200 in a response with empty content. Note that it is not always the first request and may be sent after one or more PROPFINDs. An example for the headers that are returned would be this very basic set of features:

DAV “1,2,access-control,calendar-access”
Allow “OPTIONS,GET,DELETE,PROPFIND,PUT,REPORT”

PROPFIND

This request queries calendar and calendar item information, but not the items themselves. The client will send a sequence of PROPFIND requests on different targets to determine their properties. Properties are requested as tags in the xml body. The server should either return a value in the xml if the property is found or indicate its nonexistence by declaring its status 404. Lazy clients who do not want to enumerate properties separately will try something like:

<D:propfind xmlns:D=’DAV:’><D:allprop/></D:propfind>

The requested properties vary across clients. A typical example for calendar discovery would be this request-response ping-pong game from the Mac OS iCalendar application. PROPFIND and REPORT requests should return status code 207.

PROPFIND /caldav/marmoser

<A:propfind xmlns:A=”DAV:”>
<A:prop>
<B:calendar-home-set xmlns:B=”urn:ietf:params:xml:ns:caldav”/>
<B:calendar-user-address-set xmlns:B=”urn:ietf:params:xml:ns:caldav”/>
<A:current-user-principal/>
<A:displayname/>
<C:dropbox-home-URL xmlns:C=”http://calendarserver.org/ns/”/&gt;
<C:email-address-set xmlns:C=”http://calendarserver.org/ns/”/&gt;
<C:notification-URL xmlns:C=”http://calendarserver.org/ns/”/&gt;
<A:principal-collection-set/>
<A:principal-URL/>
<A:resource-id/>
<B:schedule-inbox-URL xmlns:B=”urn:ietf:params:xml:ns:caldav”/>
<B:schedule-outbox-URL xmlns:B=”urn:ietf:params:xml:ns:caldav”/>
<A:supported-report-set/>
</A:prop>
</A:propfind>

The response would look like below. Note the http status for the different attributes.

<d:multistatus xmlns:d=”DAV:” xmlns:cs=”http://calendarserver.org/ns/&#8221; xmlns:c=”urn:ietf:params:xml:ns:caldav” xmlns:ical=”http://apple.com/ns/ical/”&gt;
<d:response>
<d:href>/caldav/marmoser</d:href>
<d:propstat>
<d:prop>
<c:calendar-home-set>
<d:href>/caldav/marmoser/calendar
</c:calendar-home-set>

<d:principal-URL>
<d:href>/caldav/marmoser/principal
</d:principal-URL>
<d:supported-report-set>
<d:supported-report>
<d:report>
<c:calendar-multiget/>
</d:report>
</d:supported-report>
<d:supported-report>
<d:report>
<c:calendar-query/>
</d:report>
</d:supported-report>
</d:supported-report-set>
</d:prop>
<d:status>HTTP/1.1 200 OK</d:status>
</d:propstat>
<d:propstat>
<d:prop>
<c:calendar-user-address-set/>
<cs:dropbox-home-URL/>
<cs:email-address-set/>
<cs:notification-URL/>
<d:resource-id/>
<c:schedule-inbox-URL/>
<c:schedule-outbox-URL/>
</d:prop>
<d:status>HTTP/1.1 404 Not Found</d:status>
</d:propstat>
</d:response>
</d:multistatus>

We notice two different urls: a principal url and a calendar url. So what exactly is the principal url? Some clients require a principal url they can query information from. Some are satisfied with the root url and the calendar url.

Now that the calendar is known, the client will try to query it:

PROPFIND /caldav/marmoser/calendar

<A:propfind xmlns:A=”DAV:”>
<A:prop>
…..
<C:getctag xmlns:C=”http://calendarserver.org/ns/”/&gt;
…..
<A:resource-id/>
<A:resourcetype/>
…..
<A:supported-report-set/>
<A:sync-token/>
</A:prop>
</A:propfind>

Let’s look at the most important attributes in greater detail.

A ctag is an important value indicating if something in the calendar has changed, usually a hash.

supported-report-set will tell the client what the server supports. In our case, we indicate support for calendar-multiget and calendar-query methods for the REPORT method.

<d:supported-report-set>
<d:supported-report>
<d:report>
<c:calendar-multiget/>
</d:report>
</d:supported-report>
<d:supported-report>
<d:report>
<c:calendar-query/>
</d:report>
</d:supported-report>
</d:supported-report-set>

sync-token returns a value if your server supports  rfc6578  synchronization. The idea is similar to the ctag: the clients sends a sync-token, the server compares if and, if a change is detected, returns the delta between the client’s and the server’s token. This is not easy to implement, since you need a data model that supports calculating and storing the changes between two sync tokens.

resourcetype will return the type of resource found under this url. For a calendar it would be <d:collection/> with DAV namespace and <c:calendar/> with CalDAV namespace.

REPORT

Now as the client will try to get the hash values for the calendar contents, the etags. Notice the time range limitation and the filters restricting the results to VEVENT type ( no VTODOs oder other resources should be returned ).

REPORT /caldav/marmoser/calendar/

<B:calendar-query xmlns:B=”urn:ietf:params:xml:ns:caldav”>
<A:prop xmlns:A=”DAV:”>
<A:getetag/>
<A:getcontenttype/>
</A:prop>
<B:filter>
<B:comp-filter name=”VCALENDAR”>
<B:comp-filter name=”VEVENT”>
<B:time-range start=”20170412T010101Z” end=”20170503T010101Z”/>
</B:comp-filter>
</B:comp-filter>
</B:filter>
</B:calendar-query>

response:

<D:multistatus xmlns:D=”DAV:” xmlns:C=”urn:ietf:params:xml:ns:caldav” xmlns:CS=”http://calendarserver.org/ns”&gt;
<D:response>
<D:href>/caldav/marmoser/calendar/20161205T084507Z-153527473.ics
<D:propstat>
<D:prop>
<D:getetag>”0bdef6e4a53d616c314fa99ff6f24aa8″</D:getetag>
<D:getcontenttype>text/calendar;charset=utf-8;component=vevent</D:getcontenttype>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
</D:multistatus>

If the etag has changed, the client will request the ics data for this calendar item. In this example, only one item is requested, but it is possible to request more than one inside a multiget. Some clients are stupid and request only one item at the time, so beware of request storms coming from android apps. The url to the ics file in href should also work when requested with a GET, and some clients will go for this.

REPORT /caldav/marmoser/calendar/

<B:calendar-multiget xmlns:B=”urn:ietf:params:xml:ns:caldav”>
<A:prop xmlns:A=”DAV:”>
<A:getetag/>
<B:calendar-data/>
<C:updated-by xmlns:C=”http://calendarserver.org/ns/”/&gt;
<C:created-by xmlns:C=”http://calendarserver.org/ns/”/&gt;
</A:prop>
<A:href xmlns:A=”DAV:”>/caldav/marmoser/calendar/20161205T084507Z-153527473.ics
</B:calendar-multiget>

Finally some calendar item data the client will be able to display.

<D:multistatus xmlns:D=”DAV:” xmlns:C=”urn:ietf:params:xml:ns:caldav” xmlns:CS=”http://calendarserver.org/ns”&gt;
<D:response>
<D:href>/caldav/marmoser/calendar/20161205T084507Z-153527473.ics</D:href>
<D:propstat>
<D:prop>
<D:getetag>”88e7895d9805b5835091108631f0ffb1″</D:getetag>
<C:calendar-data>BEGIN:VCALENDAR
X-WR-TIMEZONE:Europe/Vienna
CALSCALE:GREGORIAN
VERSION:2.0
METHOD:PUBLISH
BEGIN:VEVENT
CREATED;VALUE=DATE-TIME:20161117T092336Z
LAST-MODIFIED;VALUE=DATE-TIME:20161117T092336Z
DTSTAMP;VALUE=DATE-TIME:20161117T092336Z
DTSTART;VALUE=DATE-TIME;TZID=Europe/Vienna:20161117T150000
DTEND;VALUE=DATE-TIME;TZID=Europe/Vienna:20161117T160000
UID:20161205T084507Z-153527473
DESCRIPTION:Too wonderful for words
SUMMARY:Something wonderful
RRULE:FREQ=WEEKLY;BYDAY=TH;INTERVAL=1;UNTIL=20201116T230000Z
END:VEVENT
END:VCALENDAR
</C:calendar-data>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
<D:propstat>
<D:prop>
<CS:updated-by/>
<CS:created-by/>
</D:prop>
<D:status>HTTP/1.1 404 Not Found</D:status>
</D:propstat>
</D:response>
</D:multistatus>

Keep in mind that this is only a very basic example and does not cover the immense range of CalDAV’s possibilities. Every client ( Mac OS X, iOS, android sync apps, evolution, thunderbird etc ) will send different requests and behave differently.