Index: server/types.conf =================================================================== RCS file: /cvsroot/slim/server/types.conf,v retrieving revision 1.14 diff -u -r1.14 types.conf --- server/types.conf 15 May 2004 06:21:35 -0000 1.14 +++ server/types.conf 7 Jul 2004 21:36:57 -0000 @@ -14,6 +14,7 @@ cue cue audio/x-cue playlist dir - application/directory list flc flac,flc audio/x-flac audio +fec - audio/x-cue-flac playlist gif gif image/gif - htm htm,html text/html - ico ico image/x-icon - Index: server/CPAN/Audio/FLAC.pm =================================================================== RCS file: /cvsroot/slim/server/CPAN/Audio/FLAC.pm,v retrieving revision 1.7 diff -u -r1.7 FLAC.pm --- server/CPAN/Audio/FLAC.pm 29 Jan 2004 16:45:07 -0000 1.7 +++ server/CPAN/Audio/FLAC.pm 7 Jul 2004 21:36:58 -0000 @@ -92,6 +92,15 @@ return $self; }; + # Parse third-party application metadata block + $errflag = $self->_parseAppBlock(); + if ($errflag < 0) { + warn "[$file] Problem parsing application metadata block!"; + close FILE; + undef $self->{'fileHandle'}; + return $self; + }; + close FILE; undef $self->{'fileHandle'}; @@ -130,6 +139,17 @@ return []; } +sub application { + my $self = shift; + my $appID = shift || "default"; + + # if the application block exists, return it's content + return $self->{'application'}->{$appID} if exists($self->{'application'}->{$appID}); + + # otherwise, return nothing + return undef; +} + sub write { my $self = shift; @@ -399,6 +419,7 @@ sub _parseVorbisComments { my $self = shift; my $tags = {}; + my $rawTags = []; my $idx = $self->_findMetadataIndex(BT_VORBIS_COMMENT); # continue parsing, even if we can't find the comment. @@ -422,11 +443,14 @@ my $tagStr = substr($tmpBlock,0,$tagLen); $tmpBlock = substr($tmpBlock,$tagLen); + # Save the raw tag + push(@$rawTags, $tagStr); + # Match the key and value if ($tagStr =~ /^(.*?)=(.*)$/) { # Make the key uppercase my $tkey = $1; - $tkey =~ tr/a-z/A-Z/; + $tkey =~ tr/a-z/A-Z/; # Stick it in the tag hash $tags->{$tkey} = $2; @@ -434,6 +458,7 @@ } $self->{'tags'} = $tags; + $self->{'rawTags'} = $rawTags; return 0; } @@ -634,22 +659,43 @@ return 0; } - # Take an offset as number of flac samples +sub _parseAppBlock { + my $self = shift; + + # there may be multiple application blocks with different ids + # so we need to loop through them all. + my $idx = $self->_findMetadataIndex(BT_APPLICATION); + while ($idx >= 0) { + my $appContent = []; + + # Parse out the tags from the metadata block + my $tmpBlock = $self->{'metadataBlocks'}[$idx]->{'contents'}; + + # Find the application id + my $appID = unpack('N', substr($tmpBlock,0,4)); + + $self->{'application'}->{$appID} = substr($tmpBlock,4); + $idx = $self->_findMetadataIndex(BT_APPLICATION, ++$idx); + } + return 0; +} + +# Take an offset as number of flac samples # and return CD-DA style mm:ss:ff sub _samplesToTime { - my $samples = shift; + my $samples = shift; my $samplerate = shift; if ($samplerate == 0) { - warn "Couldn't find SAMPLERATE for time calculation!\n"; + warn "Couldn't find SAMPLERATE for time calculation!\n"; return; } my $totalSeconds = $samples / $samplerate; if ($totalSeconds == 0) { - # handled specially to avoid division by zero errors - return "00:00:00"; + # handled specially to avoid division by zero errors + return "00:00:00"; } my $trackMinutes = int(int($totalSeconds) / 60); @@ -657,7 +703,7 @@ my $trackFrames = ($totalSeconds - int($totalSeconds)) * 75; # Poor man's rounding. Needed to match the output of metaflac. - $trackFrames = int($trackFrames + 0.5); + $trackFrames = int($trackFrames + 0.5); my $formattedTime = sprintf("%02d:%02d:%02d", $trackMinutes, $trackSeconds, $trackFrames); @@ -685,8 +731,9 @@ sub _findMetadataIndex { my $self = shift; my $htype = shift; + my $idx = shift || 0; - my ($idx, $found) = (0, 0); + my $found = 0; # Loop through the metadata_blocks until one of $htype is found while ($idx < @{$self->{'metadataBlocks'}}) { Index: server/Slim/Formats/FLAC.pm =================================================================== RCS file: /cvsroot/slim/server/Slim/Formats/FLAC.pm,v retrieving revision 1.10 diff -u -r1.10 FLAC.pm --- server/Slim/Formats/FLAC.pm 26 Jun 2004 15:47:21 -0000 1.10 +++ server/Slim/Formats/FLAC.pm 7 Jul 2004 21:37:10 -0000 @@ -16,9 +16,11 @@ ############################################################################### use strict; +use File::Basename; use Audio::FLAC; use MP3::Info (); use Slim::Utils::Misc; +use Slim::Formats::Parse; my %tagMapping = ( 'TRACKNUMBER' => 'TRACKNUM', @@ -38,13 +40,63 @@ 'DATE', ); -# Given a file, return a hash of name value pairs, -# where each name is a tag name. -sub getTag { +# Choose between returning a standard tag +# or parsing through an embedded cuesheet +sub getTag { my $file = shift || ""; + my $anchor = shift || ""; my $flac = Audio::FLAC->new($file); + my $cuesheet = $flac->cuesheet(); + + # if there's no embedded cuesheet, then we're either a single song + # or we have psudo CDTEXT in the external cuesheet. + # if we do have an embedded cuesheet, but no anchor then we need to parse + # the cuesheet. + # if we have an anchor then we're already parsing it, and we look for + # metadata that matches our piece of the file. + + if (@$cuesheet > 0) { + if ($anchor eq "") { + # no anchor, handle the base file + # cue parsing will return file url references with start/end anchors + # we can now pretend that this (bare no-anchor) file is a playlist + + my $tags = getStandardTag($file, $flac); + + push(@$cuesheet, " REM END " . sprintf("%02d:%02d:%02d", + int(int($tags->{'SECS'})/60), + int($tags->{'SECS'} % 60), + (($tags->{'SECS'} - int($tags->{'SECS'})) * 75))); + $tags->{'LIST'} = Slim::Formats::Parse::parseCUE($cuesheet, dirname($file)); + + # set fields appropriate for a playlist + $tags->{'CT'} = "fec"; + $tags->{'TITLE'} = "playlist"; # $tags->{'ARTIST'} . " - " . $tags->{'ALBUM'} . " - playlist"; + + return $tags; + + } else { + # we have an anchor, so lets find metadata for this piece + return getSubFileTag($file, $anchor, $flac); + } + + } else { + #no embedded cuesheet. + #this is either a single song, or has an external cuesheet + return getStandardTag($file, $flac); + + } +} + +# Given a file, return a hash of name value pairs, +# where each name is a tag name. +sub getStandardTag { + + my $file = shift; + + my $flac = shift; my $tags = $flac->tags() || {}; @@ -56,13 +108,13 @@ # There should be a TITLE tag if the VORBIS tags are to be trusted if (defined $tags->{'TITLE'}) { - # Convert the tag values to from utf8 to latin1 - foreach my $tag (@tagNames) { - if (exists $tags->{$tag}) { - my $utf8tag = $tags->{$tag}; - $tags->{$tag} = Slim::Utils::Misc::utf8toLatin1($utf8tag); - } - } + # Convert the tag values to from utf8 to latin1 + foreach my $tag (@tagNames) { + if (exists $tags->{$tag}) { + my $utf8tag = $tags->{$tag}; + $tags->{$tag} = Slim::Utils::Misc::utf8toLatin1($utf8tag); + } + } # map the existing tag names to the expected tag names while (my ($old,$new) = each %tagMapping) { @@ -80,6 +132,26 @@ } } + addInfoTags($flac, $tags); + + return $tags; +} + +sub doTagMapping { + my $tags = shift; + + # map the existing tag names to the expected tag names + while (my ($old,$new) = each %tagMapping) { + if (exists $tags->{$old}) { + $tags->{$new} = $tags->{$old}; + delete $tags->{$old}; + } + } +} + +sub addInfoTags { + my $flac = shift; + my $tags = shift; # add more information to these tags # these are not tags, but calculated values from the streaminfo $tags->{'SIZE'} = $flac->{'fileSize'}; @@ -98,7 +170,429 @@ $tags->{'MS'} = (($tags->{'SECS'} - ($tags->{'MM'} * 60) - $tags->{'SS'}) * 1000); $tags->{'TIME'} = sprintf "%.2d:%.2d", @{$tags}{'MM', 'SS'}; +} + +sub getSubFileTag { + my $file = shift; + my $anchor = shift; + my $flac = shift; + my $tags = {}; + + # There is no official standard for + # multi-song metadata in a flac file + # so we try a few different approaches + # ordered from most useful to least + # + # as new methods are found in the wild, + # they can be added here. + # when a de-facto standard emerges, + # unused ones can be dropped. + + # TODO: streamline slimserver's flow so this parsing only happens once + # instead of repeating for each track. + + # parse embedded xml metadata + $tags = getXMLTag($file, $anchor, $flac); + return $tags if defined $tags && keys %$tags > 0; + + # look for numbered vorbis comments + $tags = getNumberedVC($file, $anchor, $flac); + return $tags if defined $tags && keys %$tags > 0; + + # parse cddb style metadata + $tags = getCDDBTag($file, $anchor, $flac); + return $tags if defined $tags && keys %$tags > 0; + + # try parsing stacked vorbis comments + $tags = getStackedVC($file, $anchor, $flac); + return $tags if defined $tags && keys %$tags > 0; + + # a not very useful last resort + return getStandardTag($file, $flac); + +} + +sub getXMLTag { + my $file = shift; + my $anchor = shift; + my $flac = shift; + my $tags = {}; + + my $PEEM = '1835361648'; #peem id (http://flac.sf.net/id.html http://peem.iconoclast.net/) + + # parse xml based metadata (musicbrainz rdf for example) + + # retrieve the xml content from the flac + my $xml = $flac->application($PEEM); + + # stop now if we don't have this + return undef unless defined $xml; + + # TODO: parse this using the same xml modules slimserver uses to parse iTunes + + # grab the cuesheet and figure out which track is current + my $cuesheet = $flac->cuesheet(); + my $tracknum = _trackFromAnchor($cuesheet, $anchor); + + # crude regex matching until we get a real rdf/xml parser in place + + # get list of albums included in this file + # TODO: handle a collection of tracks without an album association ( at a file level) + my @albumList; + if ($xml =~ m|(.+?)|m) { + my $albumListSegment = $1; + while ($albumListSegment =~ s|||m) { + push(@albumList, $1); + } + + } else { + # assume only one album + if ($xml =~ m| 0; + + # parse the individual albums to get list of tracks, etc. + my $albumHash = {}; + my $temp = $xml; + while ($temp =~ s|()||s) { + my $albumsegment = $1; + my $albumKey = ""; + if ($albumsegment =~ m|{$albumKey} = {}; + } + + if ($albumsegment =~ m|(.+?)|s) { + $albumHash->{$albumKey}->{'ALBUM'} = $1; + } + + if ($albumsegment =~ m|{$albumKey}->{'ARTISTID'} = $1; + } + + if ($albumsegment =~ m||s) { + $albumHash->{$albumKey}->{'COVER'} = $1 unless $1 eq "/images/no_coverart.png"; + # This need expanding upon to be actually useful + } + + # a cheezy way to get the first (earliest) release date + if ($albumsegment =~ m|\s*\s*.*?(.+?)|s) { + $albumHash->{$albumKey}->{'YEAR'} = $1; + } + + # grab the actual track listing + if ($albumsegment =~ m|\s*(.+?)\s*|s) { + my $trackList = $1; + while ($trackList =~ s|rdf:resource="(http://musicbrainz.org/track/[\w-]+)"||s) { + push(@{$albumHash->{$albumKey}->{'TRACKLIST'}}, $1); + } + } + } + + # merge track lists in order, and find which refers to us + my @fileTrackList = []; + for my $album (@albumList) { + push(@fileTrackList, @{$albumHash->{$album}->{'TRACKLIST'}}); + } + my $track = $fileTrackList[$tracknum]; + + # final sanity check + return undef unless defined $track; + + my $tempTags = {}; + + # now process track info for just this track + if ($xml =~ m|(.+?)|s) { + my $trackSegment = $1; + if ($trackSegment =~ m|(.+?)|s) { + $tempTags->{'TITLE'} = $1; + } + + if ($trackSegment =~ m||s) { + $tempTags->{'ARTISTID'} = $1; + } + + } + + $tempTags->{'TRACKNUM'} = $tracknum; + + # add artist info + if ($xml =~ m|{'ARTISTID'}"(.+?)|s) { + my $artistSegment = $1; + if ($artistSegment =~ m|(.+)|s) { + $tempTags->{'ARTIST'} = $1; + } + if ($artistSegment =~ m|(.+)|s) { + $tempTags->{'ARTISTSORT'} = $1; + } + } + + + # now go back through the album list and find which one matches + for my $album (@albumList) { + for my $entry (@{$albumHash->{$album}->{'TRACKLIST'}}) { + if ($entry eq $track) { + $tempTags->{'ALBUMID'} = $album; + } + } + } + + # merge the track and album results into the hash ref we intend to return + %$tags = (%{$tempTags}, %{$albumHash->{$tempTags->{'ALBUMID'}}}) if defined $tempTags->{'TITLE'};; + + addInfoTags($flac, $tags) if keys %$tags > 0; + return $tags; +} + +sub getNumberedVC { + my $file = shift; + my $anchor = shift; + my $flac = shift; + my $tags = {}; + + # parse numbered vorbis comments + # this looks for parenthetical numbers on comment keys, and + # assumes the corrosponding key/value only applies to the + # track index whose number matches. + # note that we're matching against the "actual" track number + # as reported by the cuesheet, not the "apparent" track number + # as set with the TRACKNUMBER tag. + # unnumbered keys are assumed to apply to every track. + + # as an example... + # + # ARTIST=foo + # ALBUM=bar + # TRACKNUMBER[1]=1 + # TITLE[1]=baz + # TRACKNUMBER[2]=2 + # TITLE[2]=something + + # grab the raw comments for parsing + my $rawTags = $flac->{'rawTags'}; + + # grab the cuesheet for reference + my $cuesheet = $flac->cuesheet(); + + # look for a number of parenthetical TITLE keys that matches + # the number of tracks in the cuesheet + my $titletags = 0; + my $cuetracks = 0; + + # to avoid conflicting with actual key characters, + # we allow a few different options for bracketing the track number + # allowed bracket types currently are () [] {} <> + + # we're playing a bit fast and loose here, we really should make sure + # the same bracket types are used througout, not mixed and matched. + for my $tag (@$rawTags) { + $titletags++ if $tag =~ /^\s*TITLE\s*[\(\[\{\<]\d+[\)\]\}\>]\s*=/i; + } + + for my $track (@$cuesheet) { + $cuetracks++ if $track =~ /^\s*TRACK/i; + } + + return undef unless $titletags == $cuetracks; + + # ok, let's see which tags apply to us + my $track = _trackFromAnchor($cuesheet, $anchor); + + my $tempTags = {}; + + for my $tag (@$rawTags) { + # Match the key and value + if ($tag =~ /^(.*?)=(.*)$/) { + # Make the key uppercase + my $tkey = $1; + $tkey =~ tr/a-z/A-Z/; + my $value = $2; + + # Match track number + my $group = ""; + if ($tkey =~ /^(.+)\s*[\(\[\{\<](\d+)[\)\]\}\>]/) { + $tkey = $1; + $group = $2; + } + $tempTags->{$tkey} = $value unless $group && $track != $group; + } + } + + $tags = $tempTags; + doTagMapping($tags); + addInfoTags($flac, $tags) if keys %$tags > 0; + return $tags; +} + +sub getCDDBTag { + my $file = shift; + my $anchor = shift; + my $flac = shift; + my $tags = {}; + + # parse cddb based metadata (foobar2000 does this, among others) + # it's rather crude, but probably the most widely used currently. + + # TODO: detect various artist entries that reverse title and artist + # this is non-trivial to do automatically, so I'm open to suggestions + # currently we just expect you to have fairly clean tags. + my $order = "standard"; + + $tags = $flac->tags() || {}; + + # Detect CDDB style tags by presence of DTITLE, or return. + return undef unless defined $tags->{'DTITLE'}; + + if ($tags->{'DTITLE'} =~ m|^(.+)\s*/\s*(.+)$|) { + $tags->{'ARTIST'} = $1; + $tags->{'ALBUM'} = $2; + delete $tags->{'DTITLE'}; + } + + if (exists $tags->{'DGENRE'}) { + $tags->{'GENRE'} = $tags->{'DGENRE'}; + delete $tags->{'DGENRE'}; + } + + if (exists $tags->{'DYEAR'}) { + $tags->{'YEAR'} = $tags->{'DYEAR'}; + delete $tags->{'DYEAR'}; + } + + # grab the cuesheet and figure out which track is current + my $cuesheet = $flac->cuesheet(); + my $track = _trackFromAnchor($cuesheet, $anchor); + + for my $key (keys(%$tags)) { + if ($key =~ /TTITLE(\d+)/) { + if ($track == $1) { + if ($tags->{$key} =~ m|^(.+)\s*/\s*(.+)$|) { + + if ($order eq "standard") { + $tags->{'ARTIST'} = $1; + $tags->{'TITLE'} = $2; + } else { + $tags->{'ARTIST'} = $2; + $tags->{'TITLE'} = $1; + } + + } else { + $tags->{'TITLE'} = $tags->{$key}; + } + + $tags->{'TRACKNUM'} = $track; + } + delete $tags->{$key}; + } + } + + doTagMapping($tags); + addInfoTags($flac, $tags) if keys %$tags > 0; + return $tags; +} + + +sub getStackedVC { + my $file = shift; + my $anchor = shift; + my $flac = shift; + my $tags = {}; + + # parse "stacked" vorbis comments + # this is tricky when it comes to matching which groups belong together + # particularly for various artist, or multiple album compilations. + # this as also not terribly efficent, so it's not our first choice. + + # here's a simple example of the sort of thing we're trying to work with + # + # ARTIST=foo + # ALBUM=bar + # TRACKNUMBER=1 + # TITLE=baz + # TRACKNUMBER=2 + # TITLE=something + + # grab the raw comments for parsing + my $rawTags = $flac->{'rawTags'}; + + # grab the cuesheet for reference + my $cuesheet = $flac->cuesheet(); + + # validate number of TITLE tags against number of + # tracks in the cuesheet + my $titletags = 0; + my $cuetracks = 0; + + for my $tag (@$rawTags) { + $titletags++ if $tag =~ /^\s*TITLE=/i; + } + + for my $track (@$cuesheet) { + $cuetracks++ if $track =~ /^\s*TRACK/i; + } + + return undef unless $titletags == $cuetracks; + + # ok, let's see which tags apply to us + my $track = _trackFromAnchor($cuesheet, $anchor); + + my $group = 0; + my $defaultTags = {}; + my $tempTags = {}; + + for my $tag (@$rawTags) { + # Match the key and value + if (($track != $group) && ($tag =~ /^(.*?)=(.*)$/)) { + # Make the key uppercase + my $tkey = $1; + $tkey =~ tr/a-z/A-Z/; + my $value = $2; + + if (defined $tempTags->{$tkey}) { + $group++; + my %merged = (%{$defaultTags}, %{$tempTags}); + $defaultTags = \%merged; + $tempTags = {}; + } + + $tempTags->{$tkey} = $value unless $track == $group; + } + } + + %$tags = (%{$defaultTags}, %{$tempTags}); + doTagMapping($tags); + addInfoTags($flac, $tags) if keys %$tags > 0; return $tags; +} + +sub _trackFromAnchor { + # determine a track number from a cuesheet and an anchor + + my $cuesheet = shift; + my $anchor = shift; + + return -1 unless defined $cuesheet && defined $anchor; + + my ($start) = split('-',$anchor); + + my $time = 0; + my $track = 0; + for my $line (@$cuesheet) { + if ($line =~ /\s*TRACK\s+(\d+)/i) { + $track = $1; + } + + if ($line =~ /\s*INDEX\s+01\s+(\d+):(\d+):(\d+)/i) { + $time = ($1 * 60) + $2 + ($3 / 75); + + # fudge this a bit to account for rounding + my $difference = abs($time - $start); + return $track if $difference < 0.01; + } + } } 1; Index: server/Slim/Formats/Parse.pm =================================================================== RCS file: /cvsroot/slim/server/Slim/Formats/Parse.pm,v retrieving revision 1.16 diff -u -r1.16 Parse.pm --- server/Slim/Formats/Parse.pm 18 May 2004 16:06:50 -0000 1.16 +++ server/Slim/Formats/Parse.pm 7 Jul 2004 21:37:10 -0000 @@ -199,14 +199,14 @@ if (!defined $track->{'END'}) {$track->{'END'} = $lastpos}; $lastpos = $track->{'START'}; } - + foreach my $key (sort {$a <=> $b} keys %tracks) { my $track = $tracks{$key}; if (!defined $track->{'START'} || !defined $track->{'END'} || !defined $filename ) { next; } my $url = "$filename#".$track->{'START'}."-".$track->{'END'}; - $::d_parse && msg(" url: $url\n"); - + $::d_parse && Slim::Utils::Misc::msg(" url: $url\n"); + push @items, $url; my $cacheEntry = Slim::Music::Info::cacheEntry($url); @@ -214,59 +214,66 @@ $cacheEntry->{'CT'} = Slim::Music::Info::typeFromPath($url, 'mp3'); $cacheEntry->{'TRACKNUM'} = $key; - $::d_parse && msg(" tracknum: $key\n"); - $cacheEntry->{'TITLE'} = $track->{'TITLE'}; - $::d_parse && msg(" title: " . $cacheEntry->{'TITLE'} . "\n"); - $cacheEntry->{'ARTIST'} = $track->{'ARTIST'}; - $::d_parse && msg(" artist: " . $cacheEntry->{'ARTIST'} . "\n"); + $::d_parse && Slim::Utils::Misc::msg(" tracknum: $key\n"); + if (exists $track->{'TITLE'}) { + $cacheEntry->{'TITLE'} = $track->{'TITLE'}; + $::d_parse && Slim::Utils::Misc::msg(" title: " . $cacheEntry->{'TITLE'} . "\n"); + } + if (exists $track->{'ARTIST'}) { + $cacheEntry->{'ARTIST'} = $track->{'ARTIST'}; + $::d_parse && Slim::Utils::Misc::msg(" artist: " . $cacheEntry->{'ARTIST'} . "\n"); + } if (exists $track->{'YEAR'}) { $cacheEntry->{'YEAR'} = $track->{'YEAR'}; - $::d_parse && msg(" year: " . $cacheEntry->{'YEAR'} . "\n"); + $::d_parse && Slim::Utils::Misc::msg(" year: " . $cacheEntry->{'YEAR'} . "\n"); } elsif (defined $year) { $cacheEntry->{'YEAR'} = $year; - $::d_parse && msg(" year: " . $year . "\n"); + $::d_parse && Slim::Utils::Misc::msg(" year: " . $year . "\n"); } if (exists $track->{'GENRE'}) { $cacheEntry->{'GENRE'} = $track->{'GENRE'}; - $::d_parse && msg(" genre: " . $cacheEntry->{'GENRE'} . "\n"); + $::d_parse && Slim::Utils::Misc::msg(" genre: " . $cacheEntry->{'GENRE'} . "\n"); } elsif (defined $genre) { $cacheEntry->{'GENRE'} = $genre; - $::d_parse && msg(" genre: " . $genre . "\n"); + $::d_parse && Slim::Utils::Misc::msg(" genre: " . $genre . "\n"); } if (exists $track->{'COMMENT'}) { $cacheEntry->{'COMMENT'} = $track->{'COMMENT'}; - $::d_parse && msg(" comment: " . $cacheEntry->{'COMMENT'} . "\n"); + $::d_parse && Slim::Utils::Misc::msg(" comment: " . $cacheEntry->{'COMMENT'} . "\n"); } elsif (defined $comment) { $cacheEntry->{'COMMENT'} = $comment; - $::d_parse && msg(" comment: " . $comment . "\n"); + $::d_parse && Slim::Utils::Misc::msg(" comment: " . $comment . "\n"); + } + if (defined $album) { + $cacheEntry->{'ALBUM'} = $album; + $::d_parse && Slim::Utils::Misc::msg(" album: " . $cacheEntry->{'ALBUM'} . "\n"); } - $cacheEntry->{'ALBUM'} = $album; - $::d_parse && msg(" album: " . $cacheEntry->{'ALBUM'} . "\n"); Slim::Music::Info::readTags($url); Slim::Music::Info::updateCacheEntry($url, $cacheEntry); + $cacheEntry = Slim::Music::Info::cacheEntry($url); #grab the merged info Slim::Music::Info::updateGenreCache($url, $cacheEntry); } - $::d_parse && msg(" returning: " . scalar(@items) . " items\n"); + $::d_parse && Slim::Utils::Misc::msg(" returning: " . scalar(@items) . " items\n"); return @items; } sub CUE { - my $cue = shift; my $cuefile = shift; + my $cuedir = shift; $::d_parse && msg("Parsing cue: $cuefile \n"); my @lines = (); - while (my $line = <$cue>) { + while (my $line = <$cuefile>) { chomp($line); $line =~ s/\cM//g; push @lines, $line; } - return (parseCUE([@lines], $cuefile)); + return (parseCUE([@lines], $cuedir)); } sub writePLS { Index: server/Slim/Music/Info.pm =================================================================== RCS file: /cvsroot/slim/server/Slim/Music/Info.pm,v retrieving revision 1.132 diff -u -r1.132 Info.pm --- server/Slim/Music/Info.pm 1 Jul 2004 19:06:48 -0000 1.132 +++ server/Slim/Music/Info.pm 7 Jul 2004 21:37:10 -0000 @@ -2060,7 +2060,7 @@ # Extract tag and audio info per format if (exists $tagFunctions{$type}) { - $tempCacheEntry = &{$tagFunctions{$type}}($filepath); + $tempCacheEntry = &{$tagFunctions{$type}}($filepath, $anchor); } $::d_info && !defined($tempCacheEntry) && Slim::Utils::Misc::msg("Info: no tags found for $filepath\n"); @@ -2117,9 +2117,6 @@ $::d_info && Slim::Utils::Misc::msg("readTags: calculating header $header, startbytes $startbytes and endbytes $endbytes\n"); } - # cache the content type - $tempCacheEntry->{'CT'} = $type; - if (! Slim::Music::iTunes::useiTunesLibrary()) { # Check for Cover Artwork, only if not already present. if (exists $tempCacheEntry->{'COVER'} || exists $tempCacheEntry->{'THUMB'}) {