Index: trunk/mbz
===================================================================
--- trunk/mbz	(revision 48)
+++ trunk/mbz	(revision 1)
@@ -4,28 +4,25 @@
 # one use case: for f in ~/cds/*.flac; do mbid=`./mbz --flac $f --get-release-id`; echo $f $mbid; done;
 
-use FindBin;
-use lib "$FindBin::RealBin/lib";
+use Getopt::Long;
+#use WebService::MusicBrainz;
 
-use Getopt::Long;
-use MusicBrainz;
-use DiscFlacFile;
+use LWP;
+use XML::XPath;
+use XML::XPath::XMLParser;
 
 GetOptions(
-    'flac=s'         => \my $FLAC_FILE,
-    'barcode=s'      => \my $BARCODE,
+    'flac=s' =>\my $FLAC_FILE,
     'get-release-id' => \my $GET_RELEASE_ID,
-    'xml'            => \my $GET_XML,
+    'xml' =>\my $GET_XML,
 );
 
 my $discid;
-my $barcode;
 
 if ($FLAC_FILE) {
-    my $flac_disc = DiscFlacFile->new({ file => $FLAC_FILE });
-    $discid  = $flac_disc->discid;
-    $barcode = $flac_disc->barcode;
+    require Audio::FLAC::Header;
+    my $flac = Audio::FLAC::Header->new($FLAC_FILE) or die "Can't read FLAC header from $FLAC_FILE\n";
+    $discid = $flac->tags('MBZ_DISCID') or die "No MBZ_DISCID tag in $FLAC_FILE\n";
 } else {
-    $discid  = shift;
-    $barcode = $BARCODE;
+    $discid = shift;
 }
 
@@ -33,20 +30,10 @@
 binmode STDOUT, ':utf8';
 
-# just dump the XML, if requested
-if ($GET_XML) {
-    print lookup_release($discid);
-    exit;
-}
-
-# otherwise, do the full parsing of the data
-my $info = get_musicbrainz_info({
-    discid  => $discid,
-    barcode => $barcode,
-});
+my $info = get_musicbrainz_info($discid);
 
 exit unless $info;
 
 if ($GET_RELEASE_ID) {
-    print "$$info{MUSICBRAINZ_ALBUMID}\n";
+    print "$$info{RELEASE_MBID}\n";
 } else {
     for my $key (sort keys %{ $info }) {
@@ -54,2 +41,148 @@
     }
 }
+
+sub lookup_release {
+    my ($discid) = @_;
+    my $ua = LWP::UserAgent->new;
+
+    #my $uri = URI->new('http://musicbrainz.org/ws/1/release/');
+    #$uri->query_form(type => 'xml', discid => $discid);
+    my $uri = URI->new("http://musicbrainz.org/ws/2/discid/$discid");
+    $uri->query_form(inc => 'artists+labels+recordings+release-groups+artist-credits');
+
+    my $res = $ua->get($uri);
+    # pause for a second, so we don't run afoul of the MusicBrainz API TOS
+    sleep 1;
+
+    warn $res->status_line, "\n" if $res->code != 200;
+    return if $res->code >= 400;
+    #TODO: if we get a 5xx error, retry?
+
+    return $res->decoded_content;
+}
+
+sub get_musicbrainz_info {
+    my ($discid) = @_;
+    my %info;
+
+    $info{MBZ_DISCID} = $discid;
+
+    my $xpath = XML::XPath->new();
+    my $xml = lookup_release($discid) || return;
+    
+    # just dump the XML, if requested
+    if ($GET_XML) {
+        print $xml;
+        exit;
+    }
+
+    $xpath->set_xml($xml);
+
+    # get the release; if there is more than one, take the first one
+    # TODO: configurable release selection criteria
+    my $release_count = $xpath->findvalue('count(//release)');
+    my ($release) = $xpath->findnodes('//release[1]');
+    $info{RELEASE_MBID} = $xpath->findvalue('@id', $release);
+    $info{ALBUM}        = $xpath->findvalue('title', $release);
+    $info{ARTIST}       = $xpath->findvalue('artist-credit/name-credit/artist/name', $release);
+
+    # TODO: get release date
+
+    my $ua = LWP::UserAgent->new;
+    my $tracknum = 1;
+    for my $track_node ($xpath->findnodes('.//track-list/track', $release)) {
+        my $prefix = sprintf('TRACK%02d', $tracknum);
+        #$info{"$prefix.MB_TRACKID"} = $xpath->findvalue('@id', $track_node);
+        my $recording_mbid = $info{"$prefix.RECORDING_MBID"} = $xpath->findvalue('recording/@id', $track_node);
+        $info{"$prefix.TITLE"}          = $xpath->findvalue('recording/title', $track_node);
+        $info{"$prefix.ARTIST"}         = $xpath->findvalue('recording/artist-credit/name-credit/artist/name', $track_node) || $info{ARTIST};
+        #my $uri = URI->new("http://musicbrainz.org/ws/2/recording/$recording_mbid");
+        #$uri->query_form(inc => 'artists');
+        #my $res = $ua->get($uri);
+        #die $res->decoded_content;
+
+        #TODO: get track relations (Covers, etc.)
+
+        $tracknum++;
+    }
+
+=begin
+
+    my $ws_artists = WebService::MusicBrainz->new_artist;
+    my $ws_releases = WebService::MusicBrainz->new_release;
+    my $ws_tracks = WebService::MusicBrainz->new_track;
+
+    # search on the discid
+    my $response = $ws_releases->search({ DISCID => $discid });
+
+    # save this object, since WS::MBZ deletes it when you fetch it
+    # TODO: bug report to WS::MBZ?
+    my $release = $response->release;
+
+    # return undef if there is no matching release for this DiscID
+    return unless defined $release;
+
+    # search again, using the MBID of the first release found
+    # TODO: deal with multiple releases found?
+    # include tracks and artist info
+    $response = $ws_releases->search({
+        MBID => $release->id, 
+        INC => 'discs tracks artist release-events counts',
+    });
+
+    # get the fully filled out Release object (that represents the disc)
+    $release = $response->release;
+
+    if (defined $release->artist) {
+        $info{ARTIST} = $release->artist->name;
+    }
+    if (defined $release->title) {
+        $info{ALBUM} = $release->title;
+    }
+
+    # this is ID3v2:TDRL = Release Date
+    # (for now we just take the first date)
+    my $release_date = eval { @{ $release->release_event_list->events }[0]->date };
+    $release_date = '' if $@;
+
+    $info{DATE} = $release_date;
+
+    # get full info on each of the tracks
+    my @tracks;
+    my $track_num = 1;
+    for my $track_id (map { $_->id } @{ $release->track_list->tracks }) {
+        my $response = $ws_tracks->search({ 
+            MBID => $track_id,
+            INC => 'artist track-rels',
+        });
+        my $track = $response->track;
+        my $prefix = sprintf('TRACK%02d', $track_num);
+        $info{"$prefix.TITLE"} = $track->title;
+        #if (defined $track->artist && $track->artist->name ne $release->artist->name) {
+            $info{"$prefix.ARTIST"} = $track->artist->name;
+            $info{"$prefix.DATE"} = $release_date;
+        #}
+        push @tracks, $track;
+
+
+        if (defined $track->relation_list) {
+            for my $relation (@{ $track->relation_list->relations }) {
+                #warn $relation->type, $relation->target;
+                my $response = $ws_tracks->search({
+                    MBID => $relation->target,
+                    INC => 'artist releases',
+                });
+                my $track = $response->track;
+                $info{"$prefix.ORIGINAL_ARTIST"} = $track->artist->name;
+                $info{"$prefix.ORIGINAL_ALBUM"} = 
+                    ( (@{ $track->release_list->releases })[0]->title );
+            }
+        }
+
+        $track_num++;
+    }
+
+=cut
+
+    return \%info;
+}
