summaryrefslogtreecommitdiff
path: root/lib/gcstar/GCPlugins/GCmusics/GCMusicBrainz.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gcstar/GCPlugins/GCmusics/GCMusicBrainz.pm')
-rw-r--r--lib/gcstar/GCPlugins/GCmusics/GCMusicBrainz.pm309
1 files changed, 309 insertions, 0 deletions
diff --git a/lib/gcstar/GCPlugins/GCmusics/GCMusicBrainz.pm b/lib/gcstar/GCPlugins/GCmusics/GCMusicBrainz.pm
new file mode 100644
index 0000000..f91027f
--- /dev/null
+++ b/lib/gcstar/GCPlugins/GCmusics/GCMusicBrainz.pm
@@ -0,0 +1,309 @@
+package GCPlugins::GCmusics::GCMusicBrainz;
+
+###################################################
+#
+# Copyright 2005-2010 Christian Jodar
+#
+# This file is part of GCstar.
+#
+# GCstar is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GCstar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCstar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+use utf8;
+
+use GCPlugins::GCmusics::GCmusicsCommon;
+
+{
+ package GCPlugins::GCmusics::GCPluginMusicBrainz;
+
+ use base 'GCPlugins::GCmusics::GCmusicsPluginsBase';
+ use XML::Simple;
+ use Locale::Country;
+
+ sub parse
+ {
+ my ($self, $page) = @_;
+ my $xml;
+ my $xs = XML::Simple->new;
+ if ($self->{parsingList})
+ {
+ $xml = $xs->XMLin($page,
+ ForceArray => ['release', 'event'],
+ KeyAttr => {'release' => ''});
+ my $release;
+ foreach $release ( @{ $xml->{'release-list'}->{release} } )
+ {
+ $self->{itemIdx}++;
+ $self->{itemsList}[$self->{itemIdx}]->{url} = 'http://musicbrainz.org/album/'.$release->{id}.'.html';
+ $self->{itemsList}[$self->{itemIdx}]->{title} = $release->{title};
+ $self->{itemsList}[$self->{itemIdx}]->{artist} = $release->{artist}->{name};
+
+ my $releaseDate='9999-12-31';
+ for my $releaseEvent (@{$release->{'release-event-list'}->{event}})
+ {
+ if ($releaseEvent->{date} lt $releaseDate)
+ {
+ # Find the earliest release event
+ $releaseDate = $releaseEvent->{date};
+ }
+ }
+
+ $self->{itemsList}[$self->{itemIdx}]->{release} = $releaseDate
+ if $releaseDate ne '9999-12-31';
+ }
+ }
+ else
+ {
+ $xml = $xs->XMLin($page,
+ ForceArray => ['track', 'event', 'relation', 'relation-list','tag'],
+ KeyAttr => {'track' => ''});
+ $self->{curInfo}->{title} = $xml->{release}->{title};
+ $self->{curInfo}->{web} = 'http://musicbrainz.org/release/'.$xml->{release}->{id}.'.html';
+ $self->{curInfo}->{artist} = $xml->{release}->{artist}->{name};
+ $self->{curInfo}->{ratingpress} = int($xml->{release}->{rating}->{content}) * 2;
+ $self->{curInfo}->{producer} = '';
+ $self->{curInfo}->{composer} = '';
+
+ # Step through the relations
+ for my $relation (@{$xml->{release}->{'relation-list'}})
+ {
+ if ($relation->{'target-type'} eq 'Artist')
+ {
+ # Artist type relations
+ for my $rel (@{$relation->{relation}})
+ {
+ # Search for producer or composer relations
+ $self->{curInfo}->{producer} .= $rel->{artist}->{name}.', '
+ if $rel->{type} eq 'Producer';
+ $self->{curInfo}->{composer} .= $rel->{artist}->{name}.', '
+ if $rel->{type} eq 'Composer';
+ }
+ }
+ elsif ($relation->{'target-type'} eq 'Url')
+ {
+ # Look for url type relations. Currently only jamendo works, but we should also cover the archive.org
+ # relations
+ for my $rel (@{$relation->{relation}})
+ {
+ # Alternate cover art sites
+ if (($rel->{target} =~ m/jamendo.com/) && (!$self->{curInfo}->{cover}))
+ {
+ # Cover art should be on jamendo
+ $rel->{target} =~ /\/([0-9]+)$/;
+ my $id = $1;
+ if ($self->{bigPics})
+ {
+ $self->{curInfo}->{cover} = "http://img.jamendo.com/albums/$id/covers/1.0.jpg";
+ }
+ else
+ {
+ $self->{curInfo}->{cover} = "http://img.jamendo.com/albums/$id/covers/1.200.jpg";
+ }
+ }
+ }
+ }
+ }
+
+ $self->{curInfo}->{producer} =~ s/, $//;
+ $self->{curInfo}->{composer} =~ s/, $//;
+
+ my $releaseDate;
+ my $releaseLabel;
+ my $releaseCountry;
+ my $releaseFormat;
+ my $releaseDateFromCompare='9999-12-12';
+ for my $releaseEvent (@{$xml->{release}->{'release-event-list'}->{event}})
+ {
+ my $releaseDateToCompare;
+ # Check if musicbrainz only has the year, if so, set things up so we'll prefer
+ # releases with the month & day over year-only releases
+ if (length($releaseEvent->{date}) == 4)
+ {
+ $releaseDateToCompare = $releaseEvent->{date}."-12-31";
+ }
+ else
+ {
+ $releaseDateToCompare = $releaseEvent->{date};
+ }
+
+ if (($releaseDateToCompare lt $releaseDateFromCompare) ||
+ (($releaseDateToCompare eq $releaseDateFromCompare) &&
+ (($releaseEvent->{country} eq 'US') || ($releaseEvent->{country} eq 'GB'))))
+ {
+ # Find the earliest release event, which has a month & day
+ # Big call, but we're probably more correct choosing a US or UK release if there's two
+ # release events with the same date, so prioritise them
+ $releaseDate = $releaseEvent->{date};
+ $releaseLabel = $releaseEvent->{label}->{name}
+ if $releaseEvent->{label};
+ $releaseCountry = code2country($releaseEvent->{country});
+ $releaseFormat = $releaseEvent->{format};
+ $releaseDateFromCompare = $releaseDateToCompare;
+ }
+ }
+
+ $self->{curInfo}->{release} = $releaseDate;
+ $self->{curInfo}->{label} = $releaseLabel;
+ $self->{curInfo}->{origin} = $releaseCountry;
+ $self->{curInfo}->{format} = $releaseFormat;
+
+ for my $track(@{$xml->{release}->{'track-list'}->{track}})
+ {
+ $self->addTrack($track->{title}, $track->{duration} / 1000);
+ }
+ $self->{curInfo}->{tracks} = $self->getTracks;
+ $self->{curInfo}->{running} = $self->getTotalTime;
+
+ for my $genre(@{$xml->{release}->{'tag-list'}->{tag}})
+ {
+ # Capitalize first letter of each word
+ $genre->{content} =~ s/\b(\w+)\b/ucfirst($1)/ge;
+ # Only add genres if they have more then 1 vote, strips out a lot of
+ # weird/wrong tags
+ push @{$self->{curInfo}->{genre}}, [$genre->{content}]
+ if ($genre->{count} > 1);
+ }
+
+ # If amazon artwork exists, use it
+ if (($xml->{release}->{asin}) && (!$self->{curInfo}->{cover}))
+ {
+ if ($self->{bigPics})
+ {
+ $self->{curInfo}->{cover} = 'http://images.amazon.com/images/P/'.$xml->{release}->{asin}.'.01.LZZZZZZZ.jpg'
+ }
+ else
+ {
+ $self->{curInfo}->{cover} = 'http://images.amazon.com/images/P/'.$xml->{release}->{asin}.'.01.MZZZZZZZ.jpg'
+ }
+ }
+ }
+ }
+
+ sub convertDate
+ {
+ my ($self, $date) = @_;
+ $date =~ /([0-9]{4})-?([0-9]{2})?-?([0-9]{2})?/;
+ return $3 .($3 ? '/' : '').$2.($2 ? '/' : '').$1;
+ }
+
+ sub new
+ {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+ bless ($self, $class);
+
+ $self->{hasField} = {
+ title => 1,
+ artist => 1,
+ release => 1,
+ tracks => 1
+ };
+
+ return $self;
+ }
+
+ sub preProcess
+ {
+ my ($self, $html) = @_;
+
+ return $html;
+ }
+
+ sub decodeEntitiesWanted
+ {
+ return 0;
+ }
+
+ sub getSearchUrl
+ {
+ my ($self, $word) = @_;
+
+ my $key = ($self->{searchField} eq 'artist') ? 'artist' : 'title';
+ return "http://musicbrainz.org/ws/1/release/?type=xml&$key=$word";
+ }
+
+ sub getItemUrl
+ {
+ my ($self, $url) = @_;
+ return $url if $url;
+ return "http://musicbrainz.org/";
+ }
+
+ sub changeUrl
+ {
+ my ($self, $url) = @_;
+ $url =~ s|http://musicbrainz.org/album/(.*?)\.html|http://musicbrainz.org/ws/1/release/$1?type=xml&inc=artist+tracks+release-events+artist-rels+url-rels+ratings+labels+tags|;
+ $url =~ s|http://musicbrainz.org/release/(.*?)\.html|http://musicbrainz.org/ws/1/release/$1?type=xml&inc=artist+tracks+release-events+artist-rels+url-rels+ratings+labels+tags|;
+ return $url;
+ }
+
+ sub getName
+ {
+ return 'MusicBrainz';
+ }
+
+ sub getAuthor
+ {
+ return 'Tian';
+ }
+
+ sub getLang
+ {
+ return 'EN';
+ }
+
+ sub getCharset
+ {
+ my $self = shift;
+
+ return "UTF-8";
+ }
+
+ sub getSearchCharset
+ {
+ my $self = shift;
+
+ # Need urls to be double character encoded
+ return "utf8";
+ }
+
+ sub convertCharset
+ {
+ my ($self, $value) = @_;
+ return $value;
+ }
+
+ sub getNotConverted
+ {
+ my $self = shift;
+ return [];
+ }
+
+ sub getSearchFieldsArray
+ {
+ return ['title', 'artist'];
+ }
+
+ sub isPreferred
+ {
+ # Return status of 2 means plugin is default regardless of user's language
+ return 2;
+ }
+}
+
+1;