Better handling of terminal length
[abcde.git] / cddb-tool
1 #!/bin/bash
2
3 # Copyright (C) 1999 Nathaniel Smith <njs@uclink4.berkeley.edu>
4 # Copyright (C) 1999, 2000, 2001 Robert Woodcock <rcw@debian.org>
5 # Copyright (C) 2003, 2005 Jesus Climent <jesus.climent@hispalinux.es>
6 # Copyright (c) 2012-     Steve McIntyre <93sam@@debian.org>
7 # This code is hereby licensed for public consumption under either the
8 # GNU GPL v2 or greater, or Larry Wall's Artistic License - your choice.
9 #
10 # You should have received a copy of the GNU General Public License
11 # along with this program; if not, write to the Free Software
12 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
13
14 # TODO:
15 #  - Add more error checking
16
17 # KNOWN BUGS:
18 #  - Not much error checking, esp. of arguments
19 #  - Submitted via: line is created by template, when it really should be in send.
20 #    Oh well.
21
22 VERSION=0.4.7
23 NAME=cddb-tool
24
25 #return codes
26 BAD_SYNTAX_ERR=10  # invalid CDDB file
27 NO_TMP_ERR=11      # can't create a temp file
28 NO_MATCH_ERR=12    # try submitting one
29 LOOKUP_ERR=13      # problem connecting to cddb server
30 EMPTY_QUERY_RESPONSE=14 # query response = "", (probably no net connection)
31
32 # assume a reasonable default if $HTTPGET is undefined
33 if [ "$HTTPGET" = "" ]; then
34         if [ X"$(uname)" = X"FreeBSD" ] ; then
35                 HTTPGET=fetch
36                 HTTPGETOPTS=${HTTPGETOPTS:="-q -o -"}
37         elif [ X"$(uname)" = X"NetBSD" ] ; then
38                 HTTPGET=ftp
39                 HTTPGETOPTS=${HTTPGETOPTS:="-a -V -o - "}
40         elif [ X"$(uname)" = X"Darwin" ] ; then
41                 HTTPGET=curl
42                 HTTPGETOPTS=${HTTPGETOPTS:="-f -s"}
43         else
44                 HTTPGET=wget
45                 HTTPGETOPTS=${HTTPGETOPTS:="-q -nv -e timestamping=off -O -"}
46         fi
47 fi
48
49 HTTPGET="$HTTPGET $HTTPGETOPTS"
50
51 usage() {
52           cat << EOF
53 $NAME version $VERSION
54 usage: one of:
55   $0 parse file
56   $0 template disc-id tracks
57   $0 send file address
58   $0 read server proto user host disc-id genre
59   $0 query server proto user host disc-id tracks
60   $0 stat serverurl user host proto
61   $0 help
62 EOF
63 }
64
65 help() {
66         cat << EOF
67 $NAME version $VERSION
68 A toolbox for doing cddb related stuff
69
70 Usage: $0 command [command_options]
71
72 Commands:
73   parse file
74         Get data out of a cddb file - dumps to stdout in a form
75         source'able by the shell
76
77   send file address
78         Mails a CDDB file to a specified address, using correct format.
79         Category should be one of blues, classical, country, data, folk,
80         jazz, newage, reggae, rock, soundtrack, or misc.
81   template disc-id tracks
82         Generates a template (empty) cddb file to stdout.  The command
83         line should be essentially the output of cd-discid.
84   query server proto user host disc-id tracks
85         Looks up disc on server (should be of form "http://host/~cddb/cddb.cgi")
86         remainder of command line is in the same form as that returned
87         by the cd-discid program.
88   read server proto user host disc-id genre
89         CDDB file is dumped to stdout. File will contain an extra
90         #CATEGORY= line, which leaves it a valid CDDB file but which will
91         be recognized by parse and send commands. Uses wget, so if you
92         need to use a proxy then just configure wget to do so. user and
93         host will be used for identifying ourselves to the CDDB server.
94   stat serverurl user host proto
95         Check server status with given protocol. This can be used to check
96         if the server supports given protocol. Most common values for proto
97         should be 5 and 3. With 3 you will not get DYEAR and DGENRE fields
98         in response.
99   help
100         Display this.
101 EOF
102 }
103
104 f_seq ()
105 {
106         i=$1
107         while [ $i -ne `expr $2 + 1` ]
108         do
109                 echo $i
110                 i=`expr $i + 1`
111         done
112 }
113
114 new_checkexec ()
115 {
116         if [ ! "$@" = "" ]; then
117                 # Cut off any command-line option we added in
118                 X=$(echo $@ | cut -d' ' -f2)
119                 if [ "$(which $X)" = "" ]; then
120                         return 1
121                 elif [ ! -x $(which $X) ]; then
122                         return 2
123                 fi
124         fi
125         return 0
126 }
127
128 COMMAND=$1
129 shift
130 case $COMMAND in
131 parse)  # takes 1 argument, a filename, and dumps out a sh parseable version
132         CDDBFILE="$1"
133
134         set -e
135         # names chosen to match usage in abcde code
136         DISCID=$(grep -a ^DISCID= "$CDDBFILE" | cut -f2 -d= | tr -d \[:cntrl:\])
137         DARTISTALBUM="$(grep -a ^DTITLE= "$CDDBFILE" | cut -f2- -d= | tr -d \\n | sed 's- / -~-g' | tr -d \[:cntrl:\])"
138         DARTIST="$(echo "$DARTISTALBUM" | cut -f1 -d~ | sed 's,\\,\\\\,g;s,\([\"\$\`]\),\\\1,g' | tr -d \[:cntrl:\])"
139         DALBUM="$(echo "$DARTISTALBUM" | cut -f2 -d~ | sed 's,\\,\\\\,g;s,\([\"\$\`]\),\\\1,g' | tr -d \[:cntrl:\])"
140         CDDBGENRE="$(grep -a '^#CATEGORY=' "$CDDBFILE" | cut -f2- -d= | tr -d \[:cntrl:\])"
141         if grep -a "^DYEAR" "$CDDBFILE" 2>&1 > /dev/null ; then
142                 CDYEAR=$(grep -a "^DYEAR" "$CDDBFILE" | cut -f2- -d= | tr -d \[:cntrl:\])
143         elif grep -a YEAR "$CDDBFILE" 2>&1 > /dev/null ; then
144                 CDYEAR=$(grep -a "YEAR" "$CDDBFILE" | grep -a -v "DYEAR" | awk 'BEGIN{FS="YEAR:"}{print $2}' | awk '{print $1}')
145         else
146                 CDYEAR=""
147         fi
148         CDGENRE=$(grep -a '^DGENRE=' "$CDDBFILE" | cut -f2- -d= | tr -d \[:cntrl:\])
149
150         set +e
151         echo DISCID="\"$DISCID\""
152         echo DALBUM="\"$DALBUM\""
153         echo DARTIST="\"$DARTIST\""
154         echo CDDBGENRE="\"$CDDBGENRE\""
155         echo CDYEAR="\"$CDYEAR\""
156         echo CDGENRE="\"$CDGENRE\""
157         NUMTRACKS=$(grep -a -E '^TTITLE[0-9]+=' "$CDDBFILE" | wc -l)
158         CURRTRACK=0
159         while [ "$CURRTRACK" -lt $NUMTRACKS ]; do
160                 CURRTRACKM1=$CURRTRACK # Track minus 1 (cddb numbers from 0)
161                 CURRTRACK=$(expr $CURRTRACK + 1)
162                 echo -n "TRACK${CURRTRACK}=\""
163                 grep -a ^TTITLE${CURRTRACKM1}= "$CDDBFILE" | cut -f2 -d= | sed 's,\\,\\\\,g;s,\([\"\$\`]\),\\\1,g' | tr -d \[:cntrl:\]
164                 echo \"
165         done
166         ;;
167
168 template)
169         DISCID="$@"
170         DISCNUM=$1
171         echo '# xmcd CD database file'
172         echo '#'
173         echo '# Track frame offsets:'
174         NUMTRACKS=$2
175         for x in $(f_seq 3 $(expr $NUMTRACKS + 2))
176         do
177                 printf "#\t$(echo "$DISCID" | cut -f$x -d' ')\n"
178         done
179         x=$(expr $x + 1)
180         LENGTH=$(echo "$DISCID" | cut -f$x -d' ')
181         echo "#"
182         echo "# Disc length: $LENGTH seconds"
183         echo "#"
184         echo "# Submitted via: $NAME $VERSION"
185         echo "#"
186         echo "#blues,classical,country,data,folk,jazz,newage,reggae,rock,soundtrack,misc"
187         echo "#CATEGORY=misc"
188         echo DISCID="$DISCNUM"
189         echo "DTITLE=Unknown Artist / Unknown Album"
190         echo "DYEAR="
191         echo "DGENRE="
192         # TTITLE0 -- TTITLEn
193         for x in $(f_seq 1 $NUMTRACKS)
194         do
195                 echo "TTITLE$(expr $x - 1)=Track $x"
196         done
197         echo "EXTD="
198         # EXTT0 -- EXTTn
199         for x in $(f_seq 1 $NUMTRACKS)
200         do
201                 echo "EXTT$(expr $x - 1)="
202         done
203         echo "PLAYORDER="
204         ;;
205
206 send) # cddb-tool send filename email@address
207         FILE="$1"
208         ADDRESS="$2"
209         DISCID=$(grep -a ^DISCID= "$FILE" | cut -f2 -d= | tr -d \[:cntrl:\])
210         CDDBGENRE=$(grep -a '^#CATEGORY=' "$FILE" | cut -f2- -d= | tr -d \[:cntrl:\])
211         # Use bsd-mailx by preference if we can, as it allows addition
212         # of extra headers. Otherwise, try to force UTF-8 via environment
213         if new_checkexec bsd-mailx; then
214                 grep -a -v "^#CATEGORY=" "$FILE" | iconv -t utf-8 | bsd-mailx -a "Content-Type: text/plain; charset=utf-8" -s "cddb $CDDBGENRE $DISCID" "$ADDRESS"
215         else
216                 # Find the first UTF-8 locale on the system, if any
217                 UTF_LOCALE=$(locale -a | awk '/UTF-8/ { print $1; exit}')
218                 if [ "$UTF_LOCALE"x != ""x ] ; then
219                         export LC_ALL=$UTF_LOCALE
220                 fi
221                 grep -a -v "^#CATEGORY=" "$FILE" | iconv -t utf-8 | mail -s "cddb $CDDBGENRE $DISCID" "$ADDRESS"
222         fi
223         ;;
224
225 query) # cddb-tool query serverurl proto user host discid...
226         SERVER="$1"
227         PROTO="$2"
228         USER="$3"
229         HOST="$4"
230         HELLOINFO="$USER+$HOST+$NAME+$VERSION"
231         shift 4
232         TRACKINFO="$@"
233         TRACKINFOPLUS=$(echo $TRACKINFO | tr ' ' '+')
234         RESULTS=$($HTTPGET "$SERVER?cmd=cddb+query+$TRACKINFOPLUS&hello=$HELLOINFO&proto=$PROTO") || exit $LOOKUP_ERR
235         echo "$RESULTS" | tr '\r' '\n' | tr -s '\n' | sed 's/^ //g'
236         ;;
237
238 read) # cddb-tool read serverurl proto user host genre discnumber
239         SERVER="$1"
240         PROTO="$2"
241         USER="$3"
242         HOST="$4"
243         CATEGORY="$5"
244         DISCID="$6"
245         HELLOINFO="$USER+$HOST+$NAME+$VERSION"
246         $HTTPGET $CDDBDATA "$SERVER?cmd=cddb+read+$CATEGORY+$DISCID&hello=$HELLOINFO&proto=$PROTO" 2>/dev/null
247         ;;
248
249 stat) # cddb-tool stat serverurl user host proto
250         SERVER="$1"
251         USER="$2"
252         HOST="$3"
253         PROTO="$4"
254         HELLOINFO="$USER+$HOST+$NAME+$VERSION"
255         $HTTPGET $CDDBDATA "$SERVER?cmd=stat&hello=$HELLOINFO&proto=$PROTO" 2>/dev/null
256         ;;
257
258 help) # help
259         help
260         ;;
261
262 *) # usage
263         usage
264         ;;
265 esac