From 2c2dffe6d58521463918acd4425cf9e99d8001e8 Mon Sep 17 00:00:00 2001 From: "EinvalSledge@gmail.com" Date: Fri, 13 Apr 2012 20:56:01 +0000 Subject: [PATCH] Add support for Musicbrainz using a perl helper script. git-svn-id: http://abcde.googlecode.com/svn/trunk@295 a0fa61bc-5347-0410-a1a9-7f54aa4e1825 --- FAQ | 12 +++-- Makefile | 1 + abcde | 90 ++++++++++++++++++++++++------- abcde-musicbrainz-tool | 117 +++++++++++++++++++++++++++++++++++++++++ abcde.1 | 3 +- abcde.conf | 2 + changelog | 8 +++ 7 files changed, 210 insertions(+), 23 deletions(-) create mode 100644 abcde-musicbrainz-tool diff --git a/FAQ b/FAQ index 419139b..8e136ae 100644 --- a/FAQ +++ b/FAQ @@ -3,8 +3,10 @@ Q. Who created abcde? Who develops it nowadays? A. It was originally created by Robert Woodcook. He decided to give up - maintaining it at some point in 2002 and Jesus Climent took over. Contact - jesus.climent@hispalinux.es if you have a problem or a suggestion. + maintaining it at some point in 2002 and Jesus Climent took over. In 2012, + Colin Tuckley and Steve McIntyre joined in to help. Contact + jesus.climent@hispalinux.es, colint@debian.org or 93sam@debian.org if you + have a problem or a suggestion. 1. INSTALLATION @@ -156,8 +158,8 @@ A. Yes. Use "abcde -1 -o flac -a default,cue" and it will create a single-track Ogg/Vorbis format. Of course you can select whatever format you want. -3. CDDB - ==== +3. CDDB and Musicbrainz + ==================== Q. I need to go through an HTTP proxy for CDDB access. A. No problem, just export your http_proxy variable first so wget/fetch/curl @@ -182,6 +184,8 @@ Q. After requesting CDDB data, I received several answers which seem to be A. Yes. When asked which one you want to select, use "X,Y" where X and Y are the numbers of the selections you want to find the difference between. +Q. I don't like CDDB/FreeDB. How can I use Musicbrainz instead? +A. Set CDDBMETHOD=musicbrainz and try it! 3. FORMATS ======= diff --git a/Makefile b/Makefile index 0a2c6ad..002ddea 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ install: $(INSTALL) -d -m 755 $(bindir) $(INSTALL) -m 755 -o 0 abcde $(bindir) $(INSTALL) -m 755 -o 0 cddb-tool $(bindir) + $(INSTALL) -m 755 -o 0 abcde-musicbrainz-tool $(bindir) $(INSTALL) -d -m 755 $(mandir) $(INSTALL) -m 644 -o 0 abcde.1 $(mandir) $(INSTALL) -m 644 -o 0 cddb-tool.1 $(mandir) diff --git a/abcde b/abcde index 4f36556..d585c16 100755 --- a/abcde +++ b/abcde @@ -1785,8 +1785,7 @@ do_discid () *) case "$CDDBMETHOD" in cddb) TRACKINFO=$($CDDISCID "$CDROM") ;; - # FIXME # musicbrainz needs a cleanup - musicbrainz) TRACKINFO=$($MUSICBRAINZ -c "$CDROM" ) ;; + musicbrainz) TRACKINFO=$($MUSICBRAINZ --command id --device "$CDROM") ;; esac ;; esac @@ -2218,15 +2217,76 @@ do_localcddb () fi } -do_musicbrainzstat () -{ - : -} +# do_musicbrainz +# Work with the musicbrainz WS API, then transform the results here so +# they look (very) like the results from CDDB. Maybe not the best way +# to go, but it Works For Me (TM) do_musicbrainz () { -# Use MBE_TOCGetCDIndexId on a perl query - : + if checkstatus musicbrainz-readcomplete; then :; else + vecho "Obtaining Musicbrainz results..." + # If MB is to be used, interpret the query results and read all + # the available entries. + rm -f "$ABCDETEMPDIR/cddbchoices" + CDDBCHOICES=1 # Overridden by multiple matches + ${MUSICBRAINZ} --command data --device "$CDROM" --workdir $ABCDETEMPDIR + + # The helper script will write disc matches out to + # cddbread.*. Count how many we have + NUM_RESPONSES=$(echo ${ABCDETEMPDIR}/cddbread.* | wc -w) + if [ "$NUM_RESPONSES" -eq 1 ] ; then + # One exact match + echo -n "Retrieved 1 Musicbrainz match..." >> "$ABCDETEMPDIR/cddbchoices" + echo "done." >> "$ABCDETEMPDIR/cddbchoices" + echo cddb-read-1-complete >> "$ABCDETEMPDIR/status" + echo cddb-choice=1 >> "$ABCDETEMPDIR/status" + ATITLE=$(grep -e '^DTITLE=' ${ABCDETEMPDIR}/cddbread.1 | cut -c8- ) + echo "200 none ${ATITLE}" >> "$ABCDETEMPDIR/cddbquery" + # List out disc title/author and contents + echo ---- ${ATITLE} ---- >> "$ABCDETEMPDIR/cddbchoices" + for TRACK in $(f_seq_row 1 $TRACKS) + do + echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices" + done + echo >> "$ABCDETEMPDIR/cddbchoices" + elif [ "$NUM_RESPONSES" -eq 0 ] ; then + # No matches. Use the normal cddb template for the user to + # fill in + echo "No Musicbrainz match." >> "$ABCDETEMPDIR/cddbchoices" + $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0" + # List out disc title/author and contents of template + echo ---- Unknown Artist / Unknown Album ---- >> "$ABCDETEMPDIR/cddbchoices" + UNKNOWNDISK=y + for TRACK in $(f_seq_row 1 $TRACKS) + do + echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.0" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices" + done + echo >> "$ABCDETEMPDIR/cddbchoices" + echo cddb-read-0-complete >> "$ABCDETEMPDIR/status" + echo cddb-choice=0 >> "$ABCDETEMPDIR/status" + echo 503 > "$ABCDETEMPDIR/cddbquery" + else + echo "210 Found exact matches, list follows (until terminating .)" > "$ABCDETEMPDIR/cddbquery" + echo "Multiple Musicbrainz matches:" >> "$ABCDETEMPDIR/cddbchoices" + for file in $ABCDETEMPDIR/cddbread.* + do + X=$(echo $file | sed 's/^.*cddbread\.//g') + echo cddb-read-$X-complete >> "$ABCDETEMPDIR/status" + ATITLE=$(grep -e '^DTITLE=' ${ABCDETEMPDIR}/cddbread.$X | cut -c8- ) + echo "none ${ATITLE}" >> "$ABCDETEMPDIR/cddbquery" + # List out disc title/author and contents + echo "#$X: ---- ${ATITLE} ----" >> "$ABCDETEMPDIR/cddbchoices" + for TRACK in $(f_seq_row 1 $TRACKS) + do + echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.$X" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices" + done + echo >> "$ABCDETEMPDIR/cddbchoices" + done + echo "." >> "$ABCDETEMPDIR/cddbquery" + fi + echo "musicbrainz-readcomplete" >> "$ABCDETEMPDIR/status" + fi } # do_cddbstat @@ -2972,7 +3032,7 @@ post_encode () # Builtin defaults # CDDB -# Defaults to FreeDB, but a python musicbrainz can be used +# Defaults to FreeDB, but musicbrainz can be used too, via the abcde-musicbrainz-tool script CDDBMETHOD=cddb CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi" CDDBSUBMIT=freedb-submit@freedb.org @@ -3065,7 +3125,7 @@ DAGRAB=dagrab CDDAFS=cp CDDISCID=cd-discid CDDBTOOL=cddb-tool -MUSICBRAINZ=musicbrainz-get-tracks +MUSICBRAINZ=abcde-musicbrainz-tool EJECT=eject MD5SUM=md5sum DISTMP3=distmp3 @@ -3897,14 +3957,8 @@ if [ "$DOREAD" = "y" ]; then vecho "done." fi -case "$CDDBMETHOD" in - cddb) - do_discid # Get ABCDETEMPDIR created and status file initialized - ;; - musicbrainz) - do_musicbrainz id - ;; -esac +# Get ABCDETEMPDIR created and status file initialized +do_discid if [ "$DOCDDB" = "y" ]; then # start with a sane default: diff --git a/abcde-musicbrainz-tool b/abcde-musicbrainz-tool new file mode 100644 index 0000000..7a0f567 --- /dev/null +++ b/abcde-musicbrainz-tool @@ -0,0 +1,117 @@ +#!/usr/bin/perl +# Copyright (c) 2012 Steve McIntyre <93sam@debian.org> +# This code is hereby licensed for public consumption under either the +# GNU GPL v2 or greater, or Larry Wall's Artistic license - your choice. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# abcde-musicbrainz-tool +# +# Helper script for abcde to work with the MusicBrainz WS API (v2) + +use strict; +use encoding "utf8"; +use MusicBrainz::DiscID; +use WebService::MusicBrainz::Release; +use WebService::MusicBrainz::Artist; +use WebService::MusicBrainz::Response::Track; +use WebService::MusicBrainz::Response::TrackList; +use Getopt::Long; + +my $FRAMES_PER_SEC = 75; + +my ($device, $command, $workdir); +Getopt::Long::Configure ('no_ignore_case'); +Getopt::Long::Configure ('no_auto_abbrev'); +GetOptions ("device=s" => \$device, + "command=s" => \$command, + "workdir=s" => \$workdir); + +if (!defined($device)) { + $device = "/dev/cdrom"; +} +if (!defined($command)) { + $command = "id"; +} +if (!defined($workdir)) { + $workdir = "/tmp"; +} + +my $disc = new MusicBrainz::DiscID($device); + +# read the disc in the default disc drive */ +if ( $disc->read() == 0 ) { + printf STDERR "Error: %s\n", $disc->error_msg(); + exit(1); +} + +if ($command =~ m/id/) { + + printf("%s ", $disc->id()); + printf("%d ", $disc->last_track_num() + 1 - $disc->first_track_num()); + + for ( my $i = $disc->first_track_num; + $i <= $disc->last_track_num; $i++ ) { + printf("%d ", $disc->track_offset($i)); + } + printf("%d\n", $disc->sectors() / $FRAMES_PER_SEC); + +} elsif ($command =~ m/data/) { + my $ws = WebService::MusicBrainz::Release->new(); + my $response = $ws->search({ DISCID => $disc->id()}); + my @releases = $response->release_list(); + my $releasenum = 0; + + foreach my $release (@releases) { + my $a_artist = $release->artist()->name(); + my $va = 0; + if ($a_artist =~ /Various Artists/) { + $va = 1; + } + $releasenum++; + open (OUT, "> $workdir/cddbread.$releasenum"); + binmode OUT, ":utf8"; + print OUT "# xmcd style database file\n"; + print OUT "#\n"; + print OUT "# Track frame offsets:\n"; + for ( my $i = $disc->first_track_num; + $i <= $disc->last_track_num; $i++ ) { + print OUT "# " . $disc->track_offset($i) . "\n"; + } + print OUT "#\n"; + printf OUT "# Disc length: %d seconds\n", $disc->sectors() / $FRAMES_PER_SEC; + print OUT "#\n"; + print OUT "# Submitted via: XXXXXX\n"; + print OUT "#\n"; + print OUT "#blues,classical,country,data,folk,jazz,newage,reggae,rock,soundtrack,misc\n"; + print OUT "#CATEGORY=none\n"; + print OUT "DISCID=" . $disc->id() . "\n"; + print OUT "DTITLE=" . $a_artist. " / " . $release->title() . "\n"; + print OUT "DYEAR=\n"; + print OUT "DGENRE=\n"; + + my @tracks = @{$release->track_list()->tracks()}; + for (my $i = 0; $i < scalar(@tracks); $i++) { + my $track = $tracks[$i]; + my $t_name = $track->title; + if ($va) { + my $t_artist = $track->artist->name; + printf OUT "TTITLE%d=%s / %s\n", $i, $t_artist, $t_name; + } else { + printf OUT "TTITLE%d=%s\n", $i, $t_name; + } + } + + print OUT "EXTD=\n"; + for (my $i = 0; $i < scalar(@tracks); $i++) { + printf OUT "EXTT%d=\n", $i; + } + print OUT "PLAYORDER=\n"; + print OUT ".\n"; + close OUT; + } +} + +undef $disc; diff --git a/abcde.1 b/abcde.1 index dd2c35d..706d601 100644 --- a/abcde.1 +++ b/abcde.1 @@ -245,7 +245,8 @@ Here is a list of options abcde recognizes: Specifies the method we want to use to retrieve the track information. Two values are recognized: "cddb" and "musicbrainz". The "cddb" value needs the CDDBURL and HELLOINFO variables described below. The "musicbrainz" value uses -Python to establish a conversation with the server for information retrieval. +the Perl helper script abcde-musicbrainz-tool to establish a +conversation with the Musicbrainz server for information retrieval. .TP .B CDDBURL Specifies a server to use for CDDB lookups. diff --git a/abcde.conf b/abcde.conf index 362b374..94ab5c6 100644 --- a/abcde.conf +++ b/abcde.conf @@ -5,6 +5,8 @@ # .abcde.conf file in your home directory. # CDDB options +# Choose whether you want to use CDDB or Musicbrainz. Default is CDDB +#CDDBMETHOD=cddb # If you wish to use a different CDDB server, edit this line. # If you just wanted to use a proxy server, just set your http_proxy diff --git a/changelog b/changelog index a65fdee..800535f 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,11 @@ +abcde 2.5.0, unreleased + + * Bumped to 2.5.0 + * Add support for Musicbrainz using a perl helper script. + Closes: #655970 + + -- Steve McIntyre <93sam@debian.org> Fri, 13 Apr 2011 21:25:43 +0100 + abcde 2.4.2 * Bumped to 2.4.2 -- 2.20.1