my $sock;
+my $pl_current_length;
+
# Returns a hash reference mapping filenames to an array reference listing
# the queue IDs for that file in the current play queue.
sub get_tracks_in_play_queue {
}
}
+ $pl_current_length = $pos+1;
+
return (\%matches, \%idmap);
}
my ($current, $idmap) = get_tracks_in_play_queue();
my $target = get_playlist_files($ARGV[0]);
-my $end_position = (keys %$current);
-my $num_added = 0;
my $add_start;
-sub load_tracks($) {
- my ($seq) = @_;
+sub load_tracks($$) {
+ my ($seq, $dst) = @_;
+ my ($newlen, $count);
my $start = $add_start // $seq;
+ my $add_position = $pl_current_length;
my $end = $seq+1;
- my $add_position = $end_position;
+ $dst //= $start;
+
MPD::exec("load", $ARGV[0], "$start:$end");
- $end_position += $end - $start;
- MPD::exec("move", "$add_position:$end_position", "$start")
- if ($add_position != $start);
+ MPD::exec("status");
+ MPD::exec("command_list_end");
+
+ while (<$sock>) {
+ last if (/^OK/);
+ die($_) if (/^ACK/);
+
+ if (/^(\w+): (.*)$/) {
+ if ($1 eq "playlistlength") {
+ $newlen = int($2);
+ }
+ }
+ }
+
+ $count = $newlen - $pl_current_length;
+
+ MPD::exec("command_list_begin");
+ if ($newlen > $pl_current_length) {
+ MPD::exec("move", "$add_position:$newlen", $dst)
+ if ($add_position != $dst);
+ }
+ $pl_current_length = $newlen;
undef $add_start;
+
+ return $count;
}
MPD::exec("command_list_begin");
+my ($num_added, $num_failed) = (0, 0);
for (my $i = 0; $i < @$target; $i++) {
my $f = $target->[$i];
my $id = shift @{ $current->{$f} };
- load_tracks($i - 1) if (defined $id and defined $add_start);
+ if (defined $id and defined $add_start) {
+ my $n = $i - $add_start;
+ my $m = load_tracks($i-1, $add_start - $num_failed);
+
+ $num_added += $m;
+ $num_failed += $n - $m;
+ }
if (defined $id) {
# Try not to move tracks already in the right place.
- MPD::exec("moveid", $id, $i)
- if ($i != $idmap->{$id} + $num_added);
+ MPD::exec("moveid", $id, $i - $num_failed)
+ if ($i - $num_failed != $idmap->{$id} + $num_added);
} else {
$add_start //= $i;
- $num_added++;
}
}
# Now all unwanted tracks from the original playqueue have been moved to the
# end and can be deleted all at once.
-my $pos = $add_start // @$target;
+my $pos = ($add_start // @$target) - $num_failed;
MPD::exec("delete", $pos . ":") if map { @$_ } values %$current;
MPD::exec("load", $ARGV[0], "$add_start:") if defined $add_start;
MPD::run("command_list_end");