Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
140 lines (106 sloc) 3.4 KB
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long::Descriptive;
use List::Util qw(sum);
use Mac::Glue qw(:glue);
my ($opt, $usage) = describe_options(
'%c %o',
[ 'interactive|i!', 'prompt for each album' ],
);
my $itunes = Mac::Glue->new('iTunes');
my $pl = $itunes->obj(playlist => whose(name => equals => 'Regularer'))->get;
my $albumen = $itunes->obj(playlist => whose(name => equals => 'Albumen'))->get;
die "couldn't find target playlist" unless $albumen;
{
my $tracks = $itunes->obj(
track => gAll,
playlist => $albumen->prop('index')->get,
);
$_->delete for $tracks->get;
}
print "getting tracks\n";
my @tracks = $pl->obj('tracks')->get;
my %album;
while (my $track = shift @tracks) {
my $trackid = $track->prop('database ID')->get;
my $album = $track->prop('album')->get;
my $artist = $track->prop('compilation')->get
? '-'
: $track->prop('artist')->get;
next unless defined $album and defined $artist;
next unless length $album and length $artist;
my $rec = $album{ $album, $artist } ||= [];
printf "storing record of $trackid ($album/$artist); %s left\n", 0 + @tracks;
push @$rec, {
id => $trackid,
rating => scalar $track->prop('rating')->get,
played => scalar $track->prop('played date')->get, # epoch sec
};
}
my $DEFAULT_TIME = time - 30 * 86_400;
my %avg_age;
ALBUM: for my $key (keys %album) {
my ($album, $artist) = split $;, $key;
printf "considering (%s/%s)\n", $album, $artist;
my @tracks = @{ $album{ $key } };
unless (@tracks > 4) {
printf "skipping (%s/%s); too few tracks\n", $album, $artist;
delete $album{$key};
next ALBUM;
}
my @lp_dates = map { undef $_ if $_ eq 'msng'; $_ || $DEFAULT_TIME }
map { $_->{played} }
@tracks;
my $avg_age = time - (sum(@lp_dates) / @lp_dates);
$avg_age{ $key } = $avg_age;
if ($avg_age < 86_400 * 30) {
printf "skipping (%s/%s); too recent\n", $album, $artist;
delete $album{$key};
next ALBUM;
}
my @ratings = grep { $_ > 0 } map { $_->{rating} } @tracks;
my $avg_rating = sum(@ratings) / @ratings if @ratings;
if ($avg_rating and $avg_rating < 65) {
printf "skipping (%s/%s); too lousy\n", $album, $artist;
delete $album{$key};
next ALBUM;
}
printf "keeping (%s/%s) @ %s\n", $album, $artist, $avg_rating || '(n/a)';
}
my $total_size = 0;
my %seen_artist;
my %included_track;
ADDITION: for my $key (sort { $avg_age{$b} <=> $avg_age{$a} } keys %album) {
my ($album, $artist) = split $;, $key;
if ($artist ne '-' and $seen_artist{ $artist }) {
printf "skipping (%s/%s); already have album by this artist\n",
$album, $artist;
next ADDITION;
}
if ($opt->{interactive}) {
local $|;
$|++;
for (1) {
print "include ($album by $artist)? ";
my $line = <STDIN>;
next ADDITION if $line =~ /^n/;
redo unless $line =~ /^y/;
}
}
$seen_artist{ $artist }++;
my @tracks = @{ $album{ $key } };
for my $track (@tracks) {
my $t = $itunes->obj(
track => whose('database id' => equals => $track->{id})
)->get;
$total_size += $t->prop('size')->get; # in bytes
my $dupe_track = $itunes->duplicate($t, to => $albumen);
unless ($dupe_track) {
warn "could not dupe track\n";
next;
}
$included_track{ $dupe_track->prop('database id')->get } = 1;
}
last ADDITION if $total_size > 1_000_000_000;
}