forked from hastho/pigeos
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpigeos-print
executable file
·230 lines (224 loc) · 7.56 KB
/
pigeos-print
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
#!/bin/bash
# (c) 2020-23 T.Hass
#
# USAGE pigeos-print [-P <printer>] [-d] [-m AUTO|MANUAL] <file>
#
# OPTIONS:
# <file> RAW or Postscript file to print
# -P <printer> printer to use
# -d enforce duplex mode for all documents
# -m <mode> duplex mode supported by <printer>
#
###
#
# NAME: Pi/GEOS PRINT $PIGEOS_VER
#
# PURPOSE: pre-process printer output from DOSBox and send it to a printer
#
# This helper script handles printer selection and special features to extract
# the original docuemnt name # from PS printer driver output to generate a
# unique # file name in the case the user wants to print into a PDF file. It
# also supports pre-processing of printjobs to create booklet or two-on-one
# page output und duplex printing either using PS printers which support this
# automatically (mode AUTO) or by printing odd pages first and even pages as
# second print job (mode MANUAL) after CUPS_DUPWAIT number of seconds.
#
# It reads default configuration options from $HOME/.pigeos config file:
# CUPS_DBPRN=<name> printer <name> to send output to with special names:
# AUTO means to automatically use the first availble printer
# PDF create a pdf file in $HOME/Share/PDF (drive S:\PDF)
# CUPS_DUPENF=0|1 enforce duplex mode for all documents (see -d)
# CUPS_DUPMODE=AUTO|MANUAL
# CUPS_DUPWAIT=<seconds>
#
# To enable booklet or two-on-one page printing it looks for some special tags
# in the prined GEOS document itself. These are:
# ~~BOOKLET~~ re-orders pages and prints two on one sheet of paper
# WITHOUT SCALING so your document has to be half the
# page size (e.g. A5) than the paper you want to print
# on (e.g. A4) which allows high quality prints.
# This enforced DUPLEX mode on physical printers!
# ~~TWOPAGE~~ SCALES DOWN 2 pages of the documents (+70%) to fit on
# one seet of paper. Can be combined with DUPLEX.
# ~~DUPLEX~~ Enforce duplex printing on real printers.
#
# NOTE: These options only works if 'GohstScript Software RIP' drive is used
# within GEOS! Choose white as text color to hide the tags from beeing printed.
#
# SEE ALSO: pigeos-config
#
#####
#set -e
# setup for usage and manual
PROGNAME=$(type $0 | cut -d ' ' -f 3)
PROGDIR=$(dirname $PROGNAME)
PROGNAME=$(basename $PROGNAME)
# application defaults
CONFIG=$HOME/.pigeos
PDFDIR=$HOME/Shared/PDF
LOGFILE=/tmp/pigeos-print.log
usage() {
echo "" >&2
echo "$PROGNAME:" "$@" >&2
sed -n '/^###/q; /^#/!q; s/^#//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME" >&2
exit 254
}
help() {
echo "" >&2
echo "$PROGNAME:" "$@" >&2
sed -n '/^#####/q; /^#/!q; s/^#*//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME" >&2
exit 254
}
get_doc_type() { file -b --mime-type $1; }
get_doc_name() {
# extract title and map GEOS german umlauts to UTF-8
buffer=$(strings $1 \
| grep '.*%%Title:.*' \
| sed 's/\x80/\xc3\x84/g;
s/\x8a/\xc3\xa4/g;
s/\x85/\xc3\x96/g;
s/\x9a/\xc3\xb6/g;
s/\x86/\xc3\x9c/g;
s/\x9f/\xc3\xbc/g;
s/\xa7/\xc3\x9f/g' \
)
if [ ! -z "$buffer" ]; then
echo $(expr "$buffer" : '.*%%Title: \(.*\).*'| sed 's/\s/_/g')
else
echo "unkown"
fi
}
get_doc_pcount() {
# the number of page copies requested by the user will get lost
# during the PS pre-processing, so we need to read it form input
buffer=$(strings $1 \
|grep '.*%%Requirements:\snumcopies.*'
)
if [ ! -z "$buffer" ]; then
echo $(expr "$buffer" : '.*numcopies(\([0-9]*\)).*')
else
echo 1
fi
}
get_doc_psize() {
# search for the SetPageSize line in the PgaeSetup section
buffer=$(awk '/%%BeginPageSetup/ {f=1;next} \
/%%.*/ {f=0;next} \
/.*SPS/ && f {printf("%dx%d\n", $1, $2);exit}' $1 \
)
if [ ! -z "$buffer" ]; then
echo $buffer
else
echo "595x842" # assume A4
fi
}
get_doc_booklet() { grep -q '~~BOOKLET~~' $1; }
get_doc_duplex() { grep -q '~~DUPLEX~~' $1; }
get_doc_twopage() { grep -q '~~TWOPAGE~~' $1; }
### MAIN #######################################################################
. $CONFIG
while getopts "dhP:m:" OPTION; do
case "${OPTION}" in
d) CUPS_DUPENF=1
;;
h) usage
;;
P) CUPS_DBPRN=${OPTARG}
;;
m) CUPS_DUPMODE=${OPTARG}
if [ ! \( "x$CUPS_DUPMODE" == "xAUTO" -o \
"x$CUPS_DUPMODE" == "xMANUAL" \) ]
then
usage
fi
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
if [ ! -r "${1-x}" ]; then
echo "File $1 is not readable"
exit 1
fi
### printer detection: AUTO -> select 1st form all available printers
if [ "x$CUPS_DBPRN" == "xAUTO" ]; then
printer=$(lpstat -a | cut -d ' ' -f 1)
else
# validate the desired printer is available
printer=`(lpstat -a | cut -d ' ' -f 1; echo PDF) | grep $CUPS_DBPRN`
fi
echo "Using printer '$printer' to print '$1'" >>$LOGFILE
### preparation
# extract page size information from PS input
page_size=$(get_doc_psize $1)
page_width=${page_size%x*}
page_height=${page_size#*x}
# prepare filter CMD depending options set by document tag or config
if get_doc_booklet $1; then
# double the page size for the output pipe
page_size=$((page_height))x$((page_width*2))
page_width=${page_size%x*}
page_height=${page_size#*x}
# re-order pages and place two pages next to each other
PSFILTER1="psbook"
PSFILTER2="pstops -w${page_width} -h${page_height} 2:0L(1w,0)+1L(1w,0.5h)"
elif get_doc_twopage $1; then
# scale down input page and place them next to each other
PSFILTER1="pstops -w${page_width} -h${page_height} 2:[email protected](1w,0)[email protected](1w,0.5h)"
PSFILTER2="cat"
else
# dummy filter
PSFILTER1="cat"
PSFILTER2="cat"
fi
### printing
if [ "x$printer" == "x" ]; then
echo -e "Error: no priner found" >>$LOGFILE ; exit 2
# PDF
elif [ "x$printer" == "xPDF" ]; then
# try to create PDF out dir if not present
[[ -d $PDFDIR ]] || mkdir -p $PDFDIR || exit 3
# validate printout is in Postscript format
[[ "$(get_doc_type $1)" == "application/postscript" ]] || exit 4
# convert to PDF
cat $1 | $PSFILTER1 | $PSFILTER2 | \
gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
-dCompatibilityLevel=1.1 -r72 -g"${page_size}" \
-sOutputFile="${PDFDIR}/$(get_doc_name $1).pdf" - &>>$LOGFILE
rm $1
# use a real printer
else
# command to print
if [ "x$CUPS_DUPMODE" == "xMANUAL" ]; then
# create multiple jobs, as Ghostscript strips page count from PS input
PSPRINT="lpr -# $(get_doc_pcount $1) -P $printer -J $(get_doc_name $1)"
else
# automatic duplex printing only works with PS passthrough (RAW) w/o GS
PSPRINT="lpr -P $printer -J $(get_doc_name $1)"
fi
# handle duplex printing
if get_doc_booklet $1 || get_doc_duplex $1 || test $CUPS_DUPENF -eq 1; then
if [ "x$CUPS_DUPMODE" == "xTUMBLE" ]; then
# inject PS code to instruct the printer to switch into duplex mode
cat $1 | $PSFILTER1 | $PSFILTER2 | psduplex -tumble | $PSPRINT &>>$LOGFILE
elif [ "x$CUPS_DUPMODE" == "xNOTUMBLE" ]; then
cat $1 | $PSFILTER1 | $PSFILTER2 | psduplex | $PSPRINT &>>$LOGFILE
elif [ "x$CUPS_DUPMODE" == "xMANUAL" ]; then
# create two printjobs send with a delay to allow the user to re-inject paper
# print odd pages first
cat $1 | $PSFILTER1 | $PSFILTER2 | psselect -o | $PSPRINT &>>$LOGFILE
sleep_timer=${CUPS_DUPWAIT:-30}
while [ $sleep_timer -gt 1 ]; do
echo -ne "\007"; sleep_timer=$((sleep_timer/2)); sleep $sleep_timer
done
# print even pages in reverse order
cat $1 | $PSFILTER1 | $PSFILTER2 | psselect -e -r | $PSPRINT &>>$LOGFILE
else
echo "Error: CUPS_DUPLEX=[manual|tumble|notumble] mode not set in config!" &>>$LOGFILE
fi
else # simplex printing
$PSPRINT $1 &>>$LOGFILE
fi
fi