summaryrefslogtreecommitdiffstats
path: root/juk/upcomingplaylist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'juk/upcomingplaylist.cpp')
-rw-r--r--juk/upcomingplaylist.cpp277
1 files changed, 277 insertions, 0 deletions
diff --git a/juk/upcomingplaylist.cpp b/juk/upcomingplaylist.cpp
new file mode 100644
index 00000000..a9cdbcb7
--- /dev/null
+++ b/juk/upcomingplaylist.cpp
@@ -0,0 +1,277 @@
+/***************************************************************************
+ begin : Thu Aug 19 2004
+ copyright : (C) 2002 - 2004 by Michael Pyne
+ email : michael.pyne@kde.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. *
+ * *
+ ***************************************************************************/
+
+#include <kdebug.h>
+#include <kapplication.h>
+#include <kaction.h>
+
+#include "upcomingplaylist.h"
+#include "playlistitem.h"
+#include "playlistcollection.h"
+#include "tracksequencemanager.h"
+#include "collectionlist.h"
+#include "actioncollection.h"
+
+using namespace ActionCollection;
+
+UpcomingPlaylist::UpcomingPlaylist(PlaylistCollection *collection, int defaultSize) :
+ Playlist(collection, true),
+ m_active(false),
+ m_oldIterator(0),
+ m_defaultSize(defaultSize)
+{
+ setName(i18n("Play Queue"));
+ setAllowDuplicates(true);
+ setSorting(-1);
+}
+
+UpcomingPlaylist::~UpcomingPlaylist()
+{
+ removeIteratorOverride();
+}
+
+void UpcomingPlaylist::initialize()
+{
+ // Prevent duplicate initialization.
+
+ if(m_active)
+ return;
+
+ m_active = true;
+
+ m_oldIterator = manager()->takeIterator();
+ manager()->installIterator(new UpcomingSequenceIterator(this));
+
+ if(!m_oldIterator->current())
+ m_oldIterator->prepareToPlay(CollectionList::instance());
+ else
+ manager()->iterator()->setCurrent(m_oldIterator->current());
+}
+
+void UpcomingPlaylist::appendItems(const PlaylistItemList &itemList)
+{
+ initialize();
+
+ if(itemList.isEmpty())
+ return;
+
+ PlaylistItem *after = static_cast<PlaylistItem *>(lastItem());
+
+ for(PlaylistItemList::ConstIterator it = itemList.begin(); it != itemList.end(); ++it) {
+ after = createItem(*it, after);
+ m_playlistIndex.insert(after, (*it)->playlist());
+ }
+
+ dataChanged();
+ slotWeightDirty();
+}
+
+void UpcomingPlaylist::playNext()
+{
+ initialize();
+
+ PlaylistItem *next = TrackSequenceManager::instance()->nextItem();
+
+ if(next) {
+ setPlaying(next);
+ Playlist *source = m_playlistIndex[next];
+ if(source) {
+ PlaylistList l;
+ l.append(this);
+ source->synchronizePlayingItems(l, false);
+ }
+ }
+ else {
+ removeIteratorOverride();
+
+ // Normally we continue to play the currently playing item that way
+ // a user can continue to hear their song when deselecting Play Queue.
+ // However we're technically still "playing" when the queue empties and
+ // we reinstall the old iterator so in this situation manually advance
+ // to the next track. (Otherwise we hear the same song twice in a row
+ // during the transition.
+
+ setPlaying(manager()->nextItem());
+ }
+}
+
+void UpcomingPlaylist::clearItem(PlaylistItem *item, bool emitChanged)
+{
+ m_playlistIndex.remove(item);
+ Playlist::clearItem(item, emitChanged);
+}
+
+void UpcomingPlaylist::addFiles(const QStringList &files, PlaylistItem *after)
+{
+ CollectionList::instance()->addFiles(files, after);
+
+ PlaylistItemList l;
+ for(QStringList::ConstIterator it = files.begin(); it != files.end(); ++it) {
+ FileHandle f(*it);
+ PlaylistItem *i = CollectionList::instance()->lookup(f.absFilePath());
+ if(i)
+ l.append(i);
+ }
+
+ appendItems(l);
+}
+
+QMap< PlaylistItem::Pointer, QGuardedPtr<Playlist> > &UpcomingPlaylist::playlistIndex()
+{
+ return m_playlistIndex;
+}
+
+void UpcomingPlaylist::removeIteratorOverride()
+{
+ if(!m_active)
+ return;
+
+ m_active = false; // Allow re-initialization.
+
+ if(!m_oldIterator)
+ return;
+
+ // Install the old track iterator.
+
+ manager()->installIterator(m_oldIterator);
+
+ // If we have an item that is currently playing, allow it to keep playing.
+ // Otherwise, just reset to the default iterator (probably not playing
+ // anything.)
+ // XXX: Reset to the last playing playlist?
+
+ m_oldIterator->reset();
+ if(playingItem())
+ m_oldIterator->setCurrent(playingItem()->collectionItem());
+
+ setPlaying(manager()->currentItem(), true);
+
+ Watched::currentChanged();
+}
+
+TrackSequenceManager *UpcomingPlaylist::manager() const
+{
+ return TrackSequenceManager::instance();
+}
+
+UpcomingPlaylist::UpcomingSequenceIterator::UpcomingSequenceIterator(UpcomingPlaylist *playlist) :
+ TrackSequenceIterator(), m_playlist(playlist)
+{
+}
+
+UpcomingPlaylist::UpcomingSequenceIterator::UpcomingSequenceIterator(const UpcomingSequenceIterator &other) :
+ TrackSequenceIterator(other), m_playlist(other.m_playlist)
+{
+}
+
+UpcomingPlaylist::UpcomingSequenceIterator::~UpcomingSequenceIterator()
+{
+}
+
+void UpcomingPlaylist::UpcomingSequenceIterator::advance()
+{
+ PlaylistItem *item = m_playlist->firstChild();
+
+ if(item) {
+ PlaylistItem *next = static_cast<PlaylistItem *>(item->nextSibling());
+ m_playlist->clearItem(item);
+ setCurrent(next);
+ }
+}
+
+void UpcomingPlaylist::UpcomingSequenceIterator::backup()
+{
+}
+
+UpcomingPlaylist::UpcomingSequenceIterator *UpcomingPlaylist::UpcomingSequenceIterator::clone() const
+{
+ return new UpcomingSequenceIterator(*this);
+}
+
+void UpcomingPlaylist::UpcomingSequenceIterator::setCurrent(PlaylistItem *currentItem)
+{
+ if(!currentItem) {
+ TrackSequenceIterator::setCurrent(currentItem);
+ return;
+ }
+
+ // If the upcoming playlist is playing something, clear it out since
+ // apparently the user didn't want to hear it.
+
+ PlaylistItem *playingItem = m_playlist->playingItem();
+ if(playingItem && playingItem->playlist() == m_playlist && currentItem != playingItem)
+ m_playlist->clearItem(playingItem);
+
+ // If a different playlist owns this item, add it to the upcoming playlist
+
+ Playlist *p = currentItem->playlist();
+
+ if(p != m_playlist) {
+ PlaylistItem *i = m_playlist->createItem(currentItem, (PlaylistItem *) 0);
+ m_playlist->playlistIndex().insert(i, p);
+ m_playlist->dataChanged();
+ m_playlist->slotWeightDirty();
+ }
+ else {
+ // if(p == m_playlist) {
+
+ // Bump this item up to the top
+ m_playlist->takeItem(currentItem);
+ m_playlist->insertItem(currentItem);
+ }
+
+ TrackSequenceIterator::setCurrent(m_playlist->firstChild());
+}
+
+void UpcomingPlaylist::UpcomingSequenceIterator::reset()
+{
+ setCurrent(0);
+}
+
+void UpcomingPlaylist::UpcomingSequenceIterator::prepareToPlay(Playlist *)
+{
+ if(!m_playlist->items().isEmpty())
+ setCurrent(m_playlist->firstChild());
+}
+
+QDataStream &operator<<(QDataStream &s, const UpcomingPlaylist &p)
+{
+ PlaylistItemList l = const_cast<UpcomingPlaylist *>(&p)->items();
+
+ s << Q_INT32(l.count());
+
+ for(PlaylistItemList::ConstIterator it = l.begin(); it != l.end(); ++it)
+ s << (*it)->file().absFilePath();
+
+ return s;
+}
+
+QDataStream &operator>>(QDataStream &s, UpcomingPlaylist &p)
+{
+ QString fileName;
+ PlaylistItem *newItem = 0;
+ Q_INT32 count;
+
+ s >> count;
+
+ for(Q_INT32 i = 0; i < count; ++i) {
+ s >> fileName;
+ newItem = p.createItem(FileHandle(fileName), newItem, false);
+ }
+
+ return s;
+}
+
+// vim: set et ts=4 sw=4: