aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2014-07-11 20:01:53 +0200
committerMax Kellermann <max@duempel.org>2014-07-11 20:22:35 +0200
commit11a5ee821b99da7c58da4cb2251c8686e2d615cf (patch)
tree12247daf432ae0e4de0594a9432b341b015d4a42
parenta8a85143f6e0b0fdc2467722d057a4b8526f7e69 (diff)
downloadmpd-11a5ee821b99da7c58da4cb2251c8686e2d615cf.tar.gz
mpd-11a5ee821b99da7c58da4cb2251c8686e2d615cf.tar.xz
mpd-11a5ee821b99da7c58da4cb2251c8686e2d615cf.zip
PlaylistEdit: postpone UpdateQueuedSong() when adding multiple songs
Implement a "bulk" edit mode that postpones both UpdateQueuedSong() and OnModified(). This way, the playlist version gets incremented only once. More importantly: when adding multiple songs to a queue that consists of only one song, the first song that got added will always be played next. By postponing this choice, all newly added songs get a chance to become the next song. Fixes the second (and last) part of Mantis ticket 0004005.
-rw-r--r--Makefile.am1
-rw-r--r--NEWS1
-rw-r--r--src/BulkEdit.hxx41
-rw-r--r--src/Playlist.cxx6
-rw-r--r--src/Playlist.hxx19
-rw-r--r--src/PlaylistEdit.cxx35
-rw-r--r--src/command/DatabaseCommands.cxx3
-rw-r--r--src/command/PlaylistCommands.cxx3
-rw-r--r--src/command/QueueCommands.cxx3
9 files changed, 111 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 3eb8fac0a..25352e362 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -181,6 +181,7 @@ src_mpd_SOURCES = \
src/PlaylistInfo.hxx \
src/PlaylistDatabase.cxx src/PlaylistDatabase.hxx \
src/PlaylistUpdate.cxx \
+ src/BulkEdit.hxx \
src/IdTable.hxx \
src/Queue.cxx src/Queue.hxx \
src/QueuePrint.cxx src/QueuePrint.hxx \
diff --git a/NEWS b/NEWS
index afd37bb75..198ada6a9 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,7 @@ ver 0.18.12 (not yet released)
- audiofile: fix WAV stream playback
- dsdiff, dsf: fix stream playback
* randomize next song when enabling "random" mode while not playing
+* randomize next song when adding to single-song queue
ver 0.18.11 (2014/05/12)
* decoder
diff --git a/src/BulkEdit.hxx b/src/BulkEdit.hxx
new file mode 100644
index 000000000..422dc4f38
--- /dev/null
+++ b/src/BulkEdit.hxx
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_BULK_EDIT_HXX
+#define MPD_BULK_EDIT_HXX
+
+#include "Partition.hxx"
+
+/**
+ * Begin a "bulk edit" and commit it automatically.
+ */
+class ScopeBulkEdit {
+ Partition &partition;
+
+public:
+ ScopeBulkEdit(Partition &_partition):partition(_partition) {
+ partition.playlist.BeginBulk();
+ }
+
+ ~ScopeBulkEdit() {
+ partition.playlist.CommitBulk(partition.pc);
+ }
+};
+
+#endif
diff --git a/src/Playlist.cxx b/src/Playlist.cxx
index ac2cc494b..526f35298 100644
--- a/src/Playlist.cxx
+++ b/src/Playlist.cxx
@@ -103,6 +103,12 @@ playlist::UpdateQueuedSong(PlayerControl &pc, const Song *prev)
if (!playing)
return;
+ if (prev == nullptr && bulk_edit)
+ /* postponed until CommitBulk() to avoid always
+ queueing the first song that is being added (in
+ random mode) */
+ return;
+
assert(!queue.IsEmpty());
assert((queued < 0) == (prev == nullptr));
diff --git a/src/Playlist.hxx b/src/Playlist.hxx
index 7d7e9b154..b660ecb40 100644
--- a/src/Playlist.hxx
+++ b/src/Playlist.hxx
@@ -46,6 +46,18 @@ struct playlist {
bool stop_on_error;
/**
+ * If true, then a bulk edit has been initiated by
+ * BeginBulk(), and UpdateQueuedSong() and OnModified() will
+ * be postponed until CommitBulk()
+ */
+ bool bulk_edit;
+
+ /**
+ * Has the queue been modified during bulk edit mode?
+ */
+ bool bulk_modified;
+
+ /**
* Number of errors since playback was started. If this
* number exceeds the length of the playlist, MPD gives up,
* because all songs have been tried.
@@ -69,7 +81,9 @@ struct playlist {
int queued;
playlist(unsigned max_length)
- :queue(max_length), playing(false), current(-1), queued(-1) {
+ :queue(max_length), playing(false),
+ bulk_edit(false),
+ current(-1), queued(-1) {
}
~playlist() {
@@ -126,6 +140,9 @@ protected:
void UpdateQueuedSong(PlayerControl &pc, const Song *prev);
public:
+ void BeginBulk();
+ void CommitBulk(PlayerControl &pc);
+
void Clear(PlayerControl &pc);
/**
diff --git a/src/PlaylistEdit.cxx b/src/PlaylistEdit.cxx
index 3eea2491e..0dffd3d80 100644
--- a/src/PlaylistEdit.cxx
+++ b/src/PlaylistEdit.cxx
@@ -40,6 +40,12 @@
void
playlist::OnModified()
{
+ if (bulk_edit) {
+ /* postponed to CommitBulk() */
+ bulk_modified = true;
+ return;
+ }
+
queue.IncrementVersion();
idle_add(IDLE_PLAYLIST);
@@ -56,6 +62,35 @@ playlist::Clear(PlayerControl &pc)
OnModified();
}
+void
+playlist::BeginBulk()
+{
+ assert(!bulk_edit);
+
+ bulk_edit = true;
+ bulk_modified = false;
+}
+
+void
+playlist::CommitBulk(PlayerControl &pc)
+{
+ assert(bulk_edit);
+
+ bulk_edit = false;
+ if (!bulk_modified)
+ return;
+
+ if (queued < 0)
+ /* if no song was queued, UpdateQueuedSong() is being
+ ignored in "bulk" edit mode; now that we have
+ shuffled all new songs, we can pick a random one
+ (instead of always picking the first one that was
+ added) */
+ UpdateQueuedSong(pc, nullptr);
+
+ OnModified();
+}
+
PlaylistResult
playlist::AppendFile(PlayerControl &pc,
const char *path_utf8, unsigned *added_id)
diff --git a/src/command/DatabaseCommands.cxx b/src/command/DatabaseCommands.cxx
index b86cbdae7..a7d2467b8 100644
--- a/src/command/DatabaseCommands.cxx
+++ b/src/command/DatabaseCommands.cxx
@@ -30,6 +30,7 @@
#include "util/Error.hxx"
#include "SongFilter.hxx"
#include "protocol/Result.hxx"
+#include "BulkEdit.hxx"
#include <assert.h>
#include <string.h>
@@ -92,6 +93,8 @@ handle_match_add(Client &client, int argc, char *argv[], bool fold_case)
return CommandResult::ERROR;
}
+ const ScopeBulkEdit bulk_edit(client.partition);
+
const DatabaseSelection selection("", true, &filter);
Error error;
return AddFromDatabase(client.partition, selection, error)
diff --git a/src/command/PlaylistCommands.cxx b/src/command/PlaylistCommands.cxx
index d178fa097..c4441293e 100644
--- a/src/command/PlaylistCommands.cxx
+++ b/src/command/PlaylistCommands.cxx
@@ -26,6 +26,7 @@
#include "PlaylistFile.hxx"
#include "PlaylistVector.hxx"
#include "PlaylistQueue.hxx"
+#include "BulkEdit.hxx"
#include "TimePrint.hxx"
#include "Client.hxx"
#include "protocol/ArgParser.hxx"
@@ -67,6 +68,8 @@ handle_load(Client &client, int argc, char *argv[])
} else if (!check_range(client, &start_index, &end_index, argv[2]))
return CommandResult::ERROR;
+ const ScopeBulkEdit bulk_edit(client.partition);
+
const PlaylistResult result =
playlist_open_into_queue(argv[1],
start_index, end_index,
diff --git a/src/command/QueueCommands.cxx b/src/command/QueueCommands.cxx
index a20b24132..a987e1bc9 100644
--- a/src/command/QueueCommands.cxx
+++ b/src/command/QueueCommands.cxx
@@ -28,6 +28,7 @@
#include "ClientFile.hxx"
#include "Client.hxx"
#include "Partition.hxx"
+#include "BulkEdit.hxx"
#include "protocol/ArgParser.hxx"
#include "protocol/Result.hxx"
#include "ls.hxx"
@@ -73,6 +74,8 @@ handle_add(Client &client, gcc_unused int argc, char *argv[])
return print_playlist_result(client, result);
}
+ const ScopeBulkEdit bulk_edit(client.partition);
+
const DatabaseSelection selection(uri, true);
Error error;
return AddFromDatabase(client.partition, selection, error)