This script doesn't need any metadata other than filenames and queue
IDs, so we don't need to store anything else in its data structures.
We can also ask MPD not to send us most unneeded information which
speeds things up a lot.
+# Submit a command to the MPD server and wait for it to complete.
+# Intended for simple cases where the command output is unneeded.
+sub run {
+ MPD::exec(@_);
+ while (<$sock>) {
+ last if (/^OK/);
+ die($_) if (/^ACK/);
+ }
+}
+
-# Returns a hash reference containing all tracks in the current play queue.
-# The hash keys are filenames.
+# 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 {
my %matches;
my $entry;
sub get_tracks_in_play_queue {
my %matches;
my $entry;
if (/^(\w+): (.*)$/) {
if ($1 eq "file") {
if (/^(\w+): (.*)$/) {
if ($1 eq "file") {
- if (exists($matches{$2})) {
- $entry = $matches{$2};
- } else {
- $entry = {};
- $matches{$2} = $entry;
- }
- }
-
- if (exists($entry->{$1})) {
- $entry->{$1}->{$2} = 1;
- } else {
- $entry->{$1} = { $2 => 1 }
+ $entry = $matches{$2} //= [];
+ } elsif ($1 eq "Id") {
+ push @$entry, $2;
$sock = MPD::connect();
# Retrieve the current play queue and target play queue.
$sock = MPD::connect();
# Retrieve the current play queue and target play queue.
+MPD::run("tagtypes", "clear");
my $current = get_tracks_in_play_queue();
my $target = get_playlist_files($ARGV[0]);
MPD::exec("command_list_begin");
for (my $i = 0; $i < @$target; $i++) {
my $f = $target->[$i];
my $current = get_tracks_in_play_queue();
my $target = get_playlist_files($ARGV[0]);
MPD::exec("command_list_begin");
for (my $i = 0; $i < @$target; $i++) {
my $f = $target->[$i];
- my $ids = $current->{$f}->{Id};
-
- my $id = (keys %$ids)[0];
- delete $ids->{$id};
-
- # Remove tracks with no unused queue IDs
- delete $current->{$f} unless (keys %$ids > 0);
+ my $id = shift @{ $current->{$f} };
if (defined $id) {
MPD::exec("moveid", $id, $i);
if (defined $id) {
MPD::exec("moveid", $id, $i);
}
# Remove any tracks left from the old play queue.
}
# Remove any tracks left from the old play queue.
-foreach (keys %$current) {
- my $ids = $current->{$_}->{Id};
- foreach (keys %$ids) {
- MPD::exec("deleteid", $_);
- }
-}
-
-MPD::exec("command_list_end");
-while (<$sock>) {
- last if /^OK$/;
- die($_) if /^ACK/;
-}
+MPD::exec("deleteid", $_) foreach (map { @$_ } values %$current);
+MPD::run("command_list_end");