VCS working on FreeBSD

As I wrote on the last update, I've been working on making vcs work on FreeBSD (and hopefully other non-GNU systems), there were quite a few problems that made it unusable outside GNU variants, but it's already working. Sort of:

FreeBSD Preview (small)

There's still some wrong details:
Like FreeBSD Heading Detail instead of Linux Heading Detail

or FreeBSD "Polaroid" mode sample instead of Linux "Polaroid" mode sample

But that's definitely better than not running at all 😛

The other major problem is I've no clue how the size of removable media should be retrieved (in a portable way). That's required when working with a real DVD (i.e. not a DVD ISO). The previous version used a method I disliked (fdisk -s) and that most probably would fail on everything but GNU. SO if you know of a right way of do so, drop me a line 🙂

Anyway, I'll publish this version RSN, even with this ugly bits and will look on how to fix that stuff later on.

VCS Beyond Linux

Before the next release I'd like to make VCS work better in other OSes beyond Linux. Linux is my (current at least) OS
of choice and the one I'm not familiar with so it's also obviously the OS in which I develop and test VCS.
Thanks to virtualisation
gaining a lot of momentum I'm now able to try operating systems I've never worked with (and which I'm pretty sure
will make VCS choke in ways I never expected); e.g. the very last major feature, DVD vidcapping, is written in a way not compatible
with, at least, FreeBSD. I'll focus on making vcs work better (or at all) on ther systems for a while, let's see
how it turns out.

VCS 1.0.99 released

New version released, finally implementing DVD support (both ISO and DVD devices should work).
Also JPEG 2000 output, a more Polaroid™-like

polaroid mode 😉 (the older one has been renamed to photos); the timestamp is now reduced
for smaller captures plus the usual batch of fixes/tweaks.

DVDs

Capturing from DVDs is a bit tricky, the filename is passed as an argument to -V while
the title number must be provided as if it were the file to capture, e.g.: $ vcs -V /dev/dvd 1

will capture the first title from the inserted DVD.

Passing 0 as DVD title will use the longest title in the disc (which is usually the main title):
$ vcs -V someiso.iso 0

DVD support *requires* lsdvd and fdisk (fdisk is used to detect the size of DVDs)
in this first version.

JPEG 2000

JPEG 2000 output (*.jp2 files) is used by passing the -j2 or --jpeg 2
option.

New polaroid mode

As for bugfixes: I finally came across the previously unreproducible bug that made the polaroid
and overlap modes place all images on the same spot. Guess it was a problem with a newer version of
ImageMagick since I've also encountered a lot of problems with some of the commands I was using.
I've fixed all I was able to find.
As a side effect, I've reworked once again the alignment of the different sheets.

This will be renamed as 1.1.0 if it works well enough for others.

Script: man2ps, man2pdf, man2evince

Usage:

  • $ man2ps command will generate a PostScript (.ps) file from command's manpage
  • Symlink or copy this script as "man2pdf" to create a PDF from a manpage.
  • Symlink or copy this script as "man2evince" to call evince on a temporary PDF of the manpage
#!/bin/bash

# man2ps, (c) 2004,2005,2006,2009 Toni Corvera, published under a BSD license
#
# Saves a man page as either a PostScript (PS) or as a PDF file.
#
# This script is also used as a testbed for some experiments,
# as of now only rudimentary in-file localisation is kept, in the past
# the script could also be sourced and work as a function but it led to
# unwanted pollution of the environment.
#
# $Rev: 242 $
#
# Changelog:
# 0.11.0 (2009-03-09):
#     - Added man2evince
#     - Check for man page existence
# 0.10.0 (2006-06-27):
#     - First version with a changelog
#     - Explicit usage of bash
#     - Better use of bashisms
#     - Usage of /usr/include/sysexits.h -compatible exit codes
#     - Dropped support to be used as a function (sourced)
#     - Dropped support for long options
#     - Complete help message
#     - Wrapped localized strings into functions, may help parsing speed. Or maybe not.
#     - Added set -e
#
# 0.9.2 (2005)

set -e

# Current version
VER=0.11.0
# Command name for information messages
CMD=`basename $0`

### Simple localisation support ###

# Language codes
declare -ir _EN=0 _ES=1 _CA=2
declare -a LANGS=( en es ca ) # Languages un the same order as their index
declare -i _L

# Error messages
error_nops2pdf() {
    local nopdf_strs=( "ps2pdf wasn't found, can't export to PDF"
                       "No se ha encontrado ps2pdf, no se puede exportar a PDF"
                       "No s'ha trobat ps2pdf, no es pot exportar a PDF" )
    echo ${nopdf_strs[$_L]} >&2
}

error_bad_cmdline() {
    local badcmdline_strs=( "Use -h to get usage instructions"
                            "Usa -h para obtener ayuda"
                            "Utilitza -h per obtenir ajuda" )
    echo ${badcmdline_strs[$_L]} >&2
}

error_notvalid_ver() {
    local allowedvers_strs=( "Only versions 2, 3 and 4 of ps2pdf are allowed"
                             "Sólo las versiones 2, 3 y 4 de ps2pdf están permitidas"
                             "Només les versions 2, 3 i 4 de ps2pdf estan permeses" )
    echo ${allowedvers_strs[$_L]} >&2
}

# Information messages
declare -r VERSION_STRING="${CMD} v${VER}, (c) 2004,2005,2006 Toni Corvera"

show_help() {
    # Localised functions
    en() {
        echo "$VERSION_STRING"
        echo "   saves a man page as a PostScript or PDF file"
        echo "Options:"
        echo "   -h         Show this help message"
        echo "   -p         Force PDF mode for output"
        echo "   -V VER     Use ps2pdf version 1.VER (VER must be one of 2, 3 or 4), "
        echo "              by default the newest available version is used"
    }

    es() {
        echo "$VERSION_STRING"
        echo "   guarda una página de manual como archivo PostScript o PDF"
        echo "Opciones:"
        echo "   -h         Muestra este mensaje de ayuda"
        echo "   -p         Fuerza la salida a un archivo pdf"
        echo "   -V VER     Usa la versión 1.VER de ps2pdf (VER puede ser 2, 3 o 4), "
        echo "              por defecto se usa la versión más reciente disponible"
    }

    ca() {
        echo "$VERSION_STRING"
        echo "   desa una pàgina de manual com arxiu PostScript o PDF"
        echo "Opcions:"
        echo "   -h         Mostra aquest missatge d'ajuda"
        echo "   -p         Força la sortida a un fitxer PDF"
        echo "   -V VER     Utilitza la versió 1.VER de ps2pdf (VER pot ser 2, 3 o 4), "
        echo "              per defecte s'utilitza la versió disponible més nova"
    }

    ${LANGS[$_L]}
}

show_usage() {
    local usage_strs=(
                        "Usage: ${CMD} [options] <manual page>"
                        "Uso: ${CMD} [opciones] <página del manual>"
                        "Ús: ${CMD} [opcions] <pàgina del manual>"
                     )

    echo "${usage_strs[$_L]}"
}

# $1 => ps2pdf program name
show_ps2pdf_version() {
    local pdfver_strs=( "Using ps2pdf version:"
                        "Usando ps2pdf en su variante:"
                        "Fent servir ps2pdf en sa versió:" )
    echo "${pdfver_strs[$_L]} $1" >&2
}

# Language detection
# FIXME: is the precedence order correct?
for i in LC_ALL LC_MESSAGES LANG ; do
    # Indirect variable reference, see http://www.tldp.org/LDP/abs/html/ivr.html#IVRREF
    eval val=$$i

    if [ "$val" ]; then
        case $val in
            es*) _L=$_ES ;;
            ca*) _L=$_CA ;;
            *)   _L=$_EN ;;
        esac
        break
    fi
done
if [ -z $_L ]; then _L=$_EN; fi

### Core functionality ###

declare -i PDF=0 EVINCE=0
ps2pdf=
PS2PDF_VER=

if [ $(basename "$0") == "man2pdf" ]; then
    PDF=1
elif [ $(basename "$0") == "man2evince" ]; then
    PDF=1
    EVINCE=1
fi

# Command line parsing
while getopts "hpV:" options ; do
    case $options in
        h) show_help && exit 0 ;;
        p) PDF=1 ;;
        V)
            if ! echo -n "$OPTARG" | egrep '^[234]$' >/dev/null 2>/dev/null ; then
                error_notvalid_ver
                error_bad_cmdline
                exit 64
            fi
            PS2PDF_VER=$OPTARG
        ;;
        ?)
            error_bad_cmdline
            exit 64
        ;;
    esac
done
shift $(($OPTIND - 1))

if [ -z "$1" ]; then
    show_usage
    exit 64
fi

if [ $PDF -eq 0 ]; then
    man -t "$1" > "${1}.ps"
else
    # Use the newest ps2pdf
    if [ -z "$PS2PDF_VER" ]; then
        for prog in ps2pdf14 ps2pdf13 ps2pdf12 ps2pdf ; do
            ps2pdf=`which $prog` && break
        done
    else
        ps2pdf=`which ps2pdf1$PS2PDF_VER` || true
    fi

    if [ -z "$ps2pdf" ]; then
        error_nops2pdf
        exit 69
    fi

    show_ps2pdf_version $(basename "${ps2pdf}")
    OUTPUT="${1}.pdf"
    if [ $EVINCE -eq 1 ]; then
        OUTPUT="$(tempfile --suffix=.pdf)"
    fi
    # Check if the command has a manpage...
    if ! whatis "$1" >/dev/null ; then
        man "$1" # Display man's error...
        exit $?
    fi
    man -t "$1" | ${ps2pdf} - > "$OUTPUT"
    if [ $? -eq 0 ] && [ $EVINCE -eq 1 ]; then
        evince "$OUTPUT"
        rm -f "$OUTPUT"
    fi
fi # PDF -eq 0

# vim:set ts=4 et ai: #

Downloadable file: http://p.outlyer.net/graveyard/man2ps.