[REQ] Cover art column for mp3

There's no problem extracting cover art from tags, however getting those into a column would be a bit different.
I don't thing DO supports image data through the column interface..unless it has some undocumented features.

Someone that asked about extraction earlier: Here

Maybe I misunderstood the question..Did you mean, a column saying whether the file has cover art or not?

[quote="myarmor"]There's no problem extracting cover art from tags, however getting those into a column would be a bit different.
I don't thing DO supports image data through the column interface..unless it has some undocumented features.[/quote]
Cover art can be display in column, see here : Details + Thumbnails Mode

Yes, I want to know if file has cover art or not and want to sort file by this new column.

But, I'm sure that Jon can be implement this :wink:

[quote="AlbatorV"]Yes, I want to know if file has cover art or not and want to sort file by this new column.

But, I'm sure that Jon can be implement this :wink:[/quote]
Well, this one works..although apparently not with "special" filenames (apparently Perl's -f doesn't support unicode filenames, which seems to cause MP3::Tag to fail).

Requires that ActivePerl is installed and enabled for scripting.
Enabling the default extension (.pl) for scripting can be done by extracting the attached file, then doubleclicking the .reg file.

Save as ExtractTagImagesCol.pl, or some extension you use for perl scripting.

# ExtractImagesCol - Adds a CoverArt column, and the commands ExtractTagImages and ExtractTagImage
#
# --- EXTRACTTAGIMAGE
# INFILE is the input file
# OUTFILE is the output file (including extension)
# AUTOEXT attempts to autocorrect the file extension of the output file (png, jpg, gif)
# the output filename must have an initial fileextension.

# -- EXTRACTTAGIMAGES
# OUTPATH specifies the output path for the files
# AUTOEXT attempts to autocorrect the file extension of the output file (png, jpg, gif)

use v5.14;
use warnings;
use strict;
use Win32::OLE;
use Win32::OLE qw(in valof CP_UTF8 CP_ACP OVERLOAD);
use warnings qw(FATAL utf8);
use utf8;
use Win32::OLE::Variant qw(Variant VT_BSTR);

Win32::OLE->Option(Warn => 3, CP => CP_UTF8);
use MP3::Tag;

my $useLogging=1;
sub Log{
  my $msg=shift;
  if ($useLogging){
    $::DOpus->Output($msg);
  }
}
sub OnInit{
  my $initData=shift;
  my $cmd;
  my $col;
  $initData->{name} = "ExtractTagImagesCol";
  $initData->{desc} = "Extract images from tags in selected files";
  $initData->{copyright} = "myarmor";
  $initData->{version}="0.2";
  $initData->{default_enable}=1;

  $cmd = $initData->AddCommand();
  $cmd->{desc} = "Extract coverart for selected files into the same folder (appending _output to the name), or to a specific path";
  $cmd->{hide} = 0;
  $cmd->{icon} = "info";
  $cmd->{label} = "ExtractTagImages";
  $cmd->{method} = "OnExtractTagImages";
  $cmd->{name} = "ExtractTagImages";
  $cmd->{template} = "OUTPATH/O,AUTOEXT/O";

  $cmd = $initData->AddCommand();
  $cmd->{desc} = "Extract coverart from a file";
  $cmd->{hide} = 0;
  $cmd->{icon} = "info";
  $cmd->{label} = "ExtractTagImage";
  $cmd->{method} = "OnExtractTagImage";
  $cmd->{name} = "ExtractTagImage";
  $cmd->{template} = "INFILE/K,OUTFILE/K,AUTOEXT/O";

  $col = $initData->AddColumn();
  $col->{name} = "CoverArt";
  $col->{method} = "OnCoverArt";
  $col->{label} = "CoverArt";
  $col->{autogroup} = 0;
  $col->{namerefresh}=1;
  $col->{justify} = "left";
  # $col->{defwidth}=100;
  return 0;
}

sub MimeToExt{
  my ($mime,$filename)=@_;
  if ($mime=~m/png/i){
    $filename=~s/\.[^.]+/.png/;
  } elsif ($mime=~m/gif/i){
    $filename=~s/\.[^.]+/.gif/;
  } elsif ($mime=~m/jpeg/i){
    $filename=~s/\.[^.]+/.jpg/;
  }
  return $filename;
}
sub ExtractImage{
  my ($infile,$outfile,$autoext)=@_;
  my $id3v2;
  Log("Extract image from ".$infile);
  my $mp3 = MP3::Tag->new($infile) or return 0;
  my $mime;
  # Get the tags from the MP3
  $mp3->get_tags;
  if (exists $mp3->{ID3v2}){
    $id3v2 = $mp3->{ID3v2};
    # Get the APIC frame from the Tag (The Image) which
    # returns a hash ref
    my $Pic = $id3v2->get_frame("APIC");
    if ($Pic){
      if ($autoext){
        $mime=$$Pic{'MIME type'};
        Log("Mime: ".$mime);
        $outfile=MimeToExt($mime,$outfile);
        Log("New filename: ".$outfile);
      }
      open (SAVE, ">".$outfile);
      binmode SAVE;
      print SAVE $Pic->{_Data};
      close SAVE;
      Log("Coverart found: ".$infile);
      return 1;
    } else{
      Log("NO coverart found: ".$infile);
    }
  } else{
    Log("NO ID3v2 tag found: ".$infile);
  }
  return 0;
}

sub HasCoverArt{
  my ($infile)=@_;
  my $id3v2;
  Log("Check if ".$infile." has cover art");
  my $mp3 = MP3::Tag->new($infile) or return 0;
  # Get the tags from the MP3
  $mp3->get_tags;
  if (exists $mp3->{ID3v2}){
  	Log("ID3v2 exists");
    $id3v2 = $mp3->{ID3v2};
    # Get the APIC frame from the Tag (The Image) which
    # returns a hash ref
    my $Pic = $id3v2->get_frame("APIC");
    if ($Pic){
      Log("Coverart found: ".$infile);
      return 1;
    } else {
      Log("NO coverart found: ".$infile);
      return 0;
    }
  } else{
    Log("NO ID3v2 tag found: ".$infile);
    return 0;
  }
}

# Implement the ExtractTagImages command
sub OnExtractTagImages{
  my $scriptCommandData=shift;
  my $filename;
  my $mi;
  my $Data;
  my $outpath;
  my $outfile;
  my $autoext;
  #disable deselect
  Log("ExtractTagImages");
  $scriptCommandData->func->command->{deselect}=0;
  if ($scriptCommandData->func->args->got_arg->{outpath}){
    $outpath=$scriptCommandData->func->args->{outpath};
    Log("Outpath: ".$outpath);
  }
  if ($scriptCommandData->func->args->got_arg->{autoext}){
    $autoext=$scriptCommandData->func->args->{autoext};
    Log("Autoext: ".$autoext);
  } else {
  	$autoext=0;
  }

  foreach my $item (in ($scriptCommandData->func->sourcetab->selected)){
    if ($outpath ne ''){
      $filename=valof $item->realpath;
      $outfile=$outpath."\\".$item->name;
      $outfile=~ s/\.[^.]+$/.jpg/;
      ExtractImage($filename,$outfile,$autoext);
    } else {
      $filename=valof $item->realpath;
      ExtractImage($filename,$filename."_output.jpg",$autoext);
    }
  }
}

# Implement the ExtractTagImages command
sub OnExtractTagImage{
  my $scriptCommandData=shift;
  my $filename;
  my $mi;
  my $Data;
  my $outfile;
  my $infile;
  my $autoext;
  Log("ExtractTagImage");
  #disable deselect
  $scriptCommandData->func->command->{deselect}=0;
  if ($scriptCommandData->func->args->got_arg->{infile}){
    $infile=$scriptCommandData->func->args->{infile};
    Log("Input file: ".$infile);
  }
  if ($scriptCommandData->func->args->got_arg->{outfile}){
    $outfile=$scriptCommandData->func->args->{outfile};
    Log("Output file: ".$outfile);
  }
  if ($scriptCommandData->func->args->got_arg->{autoext}){
    $autoext=$scriptCommandData->func->args->{autoext};
    Log("Autoext: ".$autoext);
  } else {
  	$autoext=0;
  }

  if (($infile ne '') && ($outfile ne '')){
    Log("Extracting coverart..");
    ExtractImage($infile,$outfile,$autoext);
    Log("Done.");
  }
}

# Handler for the CoverArt column
sub OnCoverArt{
  my $scriptColData=shift;
  if ($scriptColData->{col}!="CoverArt"){
    return;
  }
  if ($scriptColData->item->{is_dir}) {
    $scriptColData->{value} = "";
    $scriptColData->{sort} = 3;
  } else {
    if (HasCoverArt($scriptColData->item->{realpath})==1){
      $scriptColData->{value} = "YES";
    } else {
      $scriptColData->{value} = "NO";
    }
  }
}

# Called to display an About dialog for this script
sub OnAboutScript{
  my $aboutData=shift;
  my $dlg = $::DOpus->Dlg();
  $dlg->{window} = $aboutData->window;
  $dlg->{message} = "ExtractTagImagesCol";
  $dlg->{title} = "About ExtractTagImagesCol";
  $dlg->{buttons} = "OK";
  $dlg->{icon} = "info";
  $dlg->Show();
}

1;

PerlScriptReg.zip (296 Bytes)

How to use ?
I install Activeperl, put script ExtractTagImagesCol.pl in "Script Addins" folder and... nothing. :confused:

[quote="AlbatorV"]How to use ?
I install Activeperl, put script ExtractTagImagesCol.pl in "Script Addins" folder and... nothing. :confused:[/quote]
Nothing, as in?
You installed activeperl, then executed the extracted file?
Btw, the .reg file only creates a key named HKCR\Perl\ScriptEngine with a default value of "PerlScript".
That was enough to let a .pl file be used by DO etc..

Activeperl associates .pl files with Perl by default so I didn't need to do anything else.

If you open the script log (Set UTILITY=OtherLog), then place the file into the Addins folder what does the log say?

You'll probably have to completely restart DO to get DO to recognize it..which I guess means reboot nowadays.

Ah, I forgot.. Add the MP3::Tag package using PPM, or start Perl Package Manager as admin, and do the same.

ExtractTagImagesCol.pl: Erreur à la ligne 23, position 0 ExtractTagImagesCol.pl: Can't locate MP3/Tag.pm in @INC (@INC contains: C:/Perl64/site/lib C:/Perl64/lib .) (0x80004005)

Looks like your install works properly then, so installing the MP3::Tag package is what remains.
If you use perl package manager gui (as admin) you'll click the leftmost icon on the toolbar, type mp3 in the search field, go to the package
and either through rightclick menu or the action menu select Install.

You have to click File->Run marked actions or use Ctrl-Enter/Return to run the selected actions.
It doesn't run by just selecting what to install.

Huh, with v5.18 DO crashes, but with 5.16 it worked.. ugh..

Yup, ActivePerl 5.16 works with DO, but apparently 5.18 doesn't.
I've just reinstalled ActivePerl to its default location rather than having it under Program Files.

I install 5.16.3 from here activestate.com/activeperl/downloads, install package but same error Line 23

Did you do as I said.. Install MP3::Tag (Shown as MP3-Tag in Perl Package Manager)?
That error complains about missing that package ("Can't locate MP3/Tag.pm").

Make sure to use Ctrl-Return or File/Run selected actions after selecting the package for install.

When you installed ActivePerl, one of the things it installed is "Perl Package Manager" (found in the menu).

To install Mp3::Tag, start that program, and do this:


Rightclick that package and select Install
In the File menu, select "Run installed actions".

If you're going to post perl scripts that depend on a particular package being installed you should probably mention that at the start :slight_smile:

I would normally do that.. the original post for this script contained it, here.
This is basically an updated version of that script, with a coverart column, and commands for extracting coverart from one or multiple files.
Oh, and if I remember correctly these commands don't create 0 byte files when coverart doesn't exist.

For later I've made a HowTo for ActivePerl here

It's ok now, not very simple (please built in this request) but it's work...

I take it as you got the script to work. Nice.

I would also prefer it if there was some easy way to obtain the coverart binary data and related size/type/etc directly from
DOpus without having to resort to perl, python or whatever.
Alternatively, being able to (load)/save coverart (from)/to a file, and being able to get related size/type/etc for the coverart
through DO would also work.

For reference, HERE is the location of the updated script.
Some minor fixes compared to the script in this one.