Access all duplicates of a tag in a composite

Started by Nemo157, October 18, 2012, 06:00:30 AM

Previous topic - Next topic

Nemo157

I'm attempting to create a composite tag to allow accessing the myriad of ways replaygain data is stored in different formats (well, 2 ways in the formats I've looked at so far).  I've got the base case of directly copying the tag from FLAC files and just returning 0 if not set, but trying to access the ID3 tag has been presenting some difficulties.  So far I have this:


%Image::ExifTool::UserDefined = (
  'Image::ExifTool::Composite' => {
      ReplaygainAlbumGainClean => {
        Desire => {
            0 => 'ReplaygainAlbumGain',
            1 => 'UserDefinedText',
        },
        ValueConv => sub {
            my $val = shift;
            my @user = (@$val[1]);
            my @gainTags = (@$val[0]);
            foreach (@user) {
                next unless $_ && $_ =~ /replaygain_album_gain/;
                push (@gainTags, $_);
            }

            my $gain = 0;
            foreach (@gainTags) {
                next unless $_ && $_ =~ /([-+]?\d+(?:\.\d+))/;
                $gain = $1;
            }
            return $gain;
        },
      },
    },
  );
1;


But that only gets one of the UserDefinedText values.  Somehow I need to get all the duplicate values into @user so I can find the one I'm actually interested in.

Phil Harvey

If I understand correctly, there are duplicate UserDefinedText tags in the file and you want to scan through them all.  This is a bit tricky since it gets into the ExifTool internals a bit.  There may be better ways to do this, but the one that occurs to me is to do this in your ValueConv:

    for (my $i=0; ; ++$i) {
        my $tagKey = 'UserDefinedText';
        $tagKey .= " ($i)" if $i;
        my $val = Sself->GetValue($tagKey);
        last unless defined $val;
        # process value here
    }


- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

Nemo157

That's exactly what I wanted to do.  For some reason using GetValue wouldn't let me access the duplicates still, but GetInfo did  :).  My final ValueConv was:


my $val = shift;
my $self = shift;

my @gainTags = (@$val[0]);
my $userTags = $self->GetInfo("*:UserDefinedText");
foreach (values %$userTags) {
    next unless $_ && $_ =~ /replaygain_album_gain/
    push (@gainTags, $_);
}

my $gain = 0;
foreach (@gainTags) {
    next unless $_ && $_ =~ /([+-]?\d+(?:\.\d+)?)/;
    $gain = $1;
}
return $gain;


Thanks.

Phil Harvey

I would be careful using GetInfo from within a ValueConv because it will overwrite information in the ExifTool object that was retrieved from the previous GetInfo call.  This is why I used my knowledge of the internal tag keys instead.  I should think about this to see if there is a better solution.

- Phil

...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).