source: flacrip/trunk/mbz @ 1

Last change on this file since 1 was 1, checked in by peter, 13 years ago

initial import of current flacrip files into the trunk

  • Property svn:executable set to *
File size: 5.8 KB
Line 
1#!/usr/bin/perl -w
2use strict;
3
4# one use case: for f in ~/cds/*.flac; do mbid=`./mbz --flac $f --get-release-id`; echo $f $mbid; done;
5
6use Getopt::Long;
7#use WebService::MusicBrainz;
8
9use LWP;
10use XML::XPath;
11use XML::XPath::XMLParser;
12
13GetOptions(
14    'flac=s' =>\my $FLAC_FILE,
15    'get-release-id' => \my $GET_RELEASE_ID,
16    'xml' =>\my $GET_XML,
17);
18
19my $discid;
20
21if ($FLAC_FILE) {
22    require Audio::FLAC::Header;
23    my $flac = Audio::FLAC::Header->new($FLAC_FILE) or die "Can't read FLAC header from $FLAC_FILE\n";
24    $discid = $flac->tags('MBZ_DISCID') or die "No MBZ_DISCID tag in $FLAC_FILE\n";
25} else {
26    $discid = shift;
27}
28
29# make the output terminal handle UTF-8 characters
30binmode STDOUT, ':utf8';
31
32my $info = get_musicbrainz_info($discid);
33
34exit unless $info;
35
36if ($GET_RELEASE_ID) {
37    print "$$info{RELEASE_MBID}\n";
38} else {
39    for my $key (sort keys %{ $info }) {
40        print "$key=$$info{$key}\n";
41    }
42}
43
44sub lookup_release {
45    my ($discid) = @_;
46    my $ua = LWP::UserAgent->new;
47
48    #my $uri = URI->new('http://musicbrainz.org/ws/1/release/');
49    #$uri->query_form(type => 'xml', discid => $discid);
50    my $uri = URI->new("http://musicbrainz.org/ws/2/discid/$discid");
51    $uri->query_form(inc => 'artists+labels+recordings+release-groups+artist-credits');
52
53    my $res = $ua->get($uri);
54    # pause for a second, so we don't run afoul of the MusicBrainz API TOS
55    sleep 1;
56
57    warn $res->status_line, "\n" if $res->code != 200;
58    return if $res->code >= 400;
59    #TODO: if we get a 5xx error, retry?
60
61    return $res->decoded_content;
62}
63
64sub get_musicbrainz_info {
65    my ($discid) = @_;
66    my %info;
67
68    $info{MBZ_DISCID} = $discid;
69
70    my $xpath = XML::XPath->new();
71    my $xml = lookup_release($discid) || return;
72   
73    # just dump the XML, if requested
74    if ($GET_XML) {
75        print $xml;
76        exit;
77    }
78
79    $xpath->set_xml($xml);
80
81    # get the release; if there is more than one, take the first one
82    # TODO: configurable release selection criteria
83    my $release_count = $xpath->findvalue('count(//release)');
84    my ($release) = $xpath->findnodes('//release[1]');
85    $info{RELEASE_MBID} = $xpath->findvalue('@id', $release);
86    $info{ALBUM}        = $xpath->findvalue('title', $release);
87    $info{ARTIST}       = $xpath->findvalue('artist-credit/name-credit/artist/name', $release);
88
89    # TODO: get release date
90
91    my $ua = LWP::UserAgent->new;
92    my $tracknum = 1;
93    for my $track_node ($xpath->findnodes('.//track-list/track', $release)) {
94        my $prefix = sprintf('TRACK%02d', $tracknum);
95        #$info{"$prefix.MB_TRACKID"} = $xpath->findvalue('@id', $track_node);
96        my $recording_mbid = $info{"$prefix.RECORDING_MBID"} = $xpath->findvalue('recording/@id', $track_node);
97        $info{"$prefix.TITLE"}          = $xpath->findvalue('recording/title', $track_node);
98        $info{"$prefix.ARTIST"}         = $xpath->findvalue('recording/artist-credit/name-credit/artist/name', $track_node) || $info{ARTIST};
99        #my $uri = URI->new("http://musicbrainz.org/ws/2/recording/$recording_mbid");
100        #$uri->query_form(inc => 'artists');
101        #my $res = $ua->get($uri);
102        #die $res->decoded_content;
103
104        #TODO: get track relations (Covers, etc.)
105
106        $tracknum++;
107    }
108
109=begin
110
111    my $ws_artists = WebService::MusicBrainz->new_artist;
112    my $ws_releases = WebService::MusicBrainz->new_release;
113    my $ws_tracks = WebService::MusicBrainz->new_track;
114
115    # search on the discid
116    my $response = $ws_releases->search({ DISCID => $discid });
117
118    # save this object, since WS::MBZ deletes it when you fetch it
119    # TODO: bug report to WS::MBZ?
120    my $release = $response->release;
121
122    # return undef if there is no matching release for this DiscID
123    return unless defined $release;
124
125    # search again, using the MBID of the first release found
126    # TODO: deal with multiple releases found?
127    # include tracks and artist info
128    $response = $ws_releases->search({
129        MBID => $release->id,
130        INC => 'discs tracks artist release-events counts',
131    });
132
133    # get the fully filled out Release object (that represents the disc)
134    $release = $response->release;
135
136    if (defined $release->artist) {
137        $info{ARTIST} = $release->artist->name;
138    }
139    if (defined $release->title) {
140        $info{ALBUM} = $release->title;
141    }
142
143    # this is ID3v2:TDRL = Release Date
144    # (for now we just take the first date)
145    my $release_date = eval { @{ $release->release_event_list->events }[0]->date };
146    $release_date = '' if $@;
147
148    $info{DATE} = $release_date;
149
150    # get full info on each of the tracks
151    my @tracks;
152    my $track_num = 1;
153    for my $track_id (map { $_->id } @{ $release->track_list->tracks }) {
154        my $response = $ws_tracks->search({
155            MBID => $track_id,
156            INC => 'artist track-rels',
157        });
158        my $track = $response->track;
159        my $prefix = sprintf('TRACK%02d', $track_num);
160        $info{"$prefix.TITLE"} = $track->title;
161        #if (defined $track->artist && $track->artist->name ne $release->artist->name) {
162            $info{"$prefix.ARTIST"} = $track->artist->name;
163            $info{"$prefix.DATE"} = $release_date;
164        #}
165        push @tracks, $track;
166
167
168        if (defined $track->relation_list) {
169            for my $relation (@{ $track->relation_list->relations }) {
170                #warn $relation->type, $relation->target;
171                my $response = $ws_tracks->search({
172                    MBID => $relation->target,
173                    INC => 'artist releases',
174                });
175                my $track = $response->track;
176                $info{"$prefix.ORIGINAL_ARTIST"} = $track->artist->name;
177                $info{"$prefix.ORIGINAL_ALBUM"} =
178                    ( (@{ $track->release_list->releases })[0]->title );
179            }
180        }
181
182        $track_num++;
183    }
184
185=cut
186
187    return \%info;
188}
Note: See TracBrowser for help on using the repository browser.