Commit 5fc3e83d authored by Scott Wheeler's avatar Scott Wheeler

Ok, more than five hours late and coolo still hasn't turned me into a pumpkin.

I've been assured that this will happen in the morning, though after three hours
of sleep, I think the effect would be natural.

The moral of the story:  test features in apps you maintain before the day of the
freeze.  (I knew that the play queue was broken, but not quite how badly -- this
was mostly Michael's turf, but he's away for another few weeks.)

Ok, so stuff that happened:

Fixed the "magical not-showing-back-up" Play Queue (was related to saving the
play queue, which even when set up properly just caused all sorts of crashes.
Commented out for now, ideally to be reenabled in 3.4.1) -- #99191

Fixed up a lot of the quirkiness with the interaction of the Play Queue and the
rest of the application playlists.  This hopefully fixes #98473 (if not, just
reopen)

Double clicking on an item (anywhere) plays it immediately. #97021

And the catch all, #88888, "this sucks" was mostly implemented.  Some of the things
I took a different line on, but you got at least 3 of the 6.  The last two I don't
agree with.  If you feel so compelled, open more specific requests from here on out.

Basically this structurally changed things so that instead of adding items to the
play queue when turned on and always using that as the main location for playing
now the play queue is only used when there's stuff in it.  When it's empty again
playing resumes in the list that the last item in the play queue came from.  It
will jump back into the play queue as soon as something is added.

This is still a little rough, but it doesn't crash all the time like it was before
(fixed at least three crashes on this one) and is close enough to actually being
releasable for me to now get a couple hours sleep.

BUG:99191
BUG:98473
BUG:97021
BUG:88888

svn path=/trunk/kdemultimedia/juk/; revision=392533
parent ba536bcb
......@@ -147,11 +147,13 @@ void Cache::loadPlaylists(PlaylistCollection *collection) // static
}
case Upcoming:
{
UpcomingPlaylist *p = new UpcomingPlaylist(collection);
/*
collection->setUpcomingPlaylistEnabled(true);
Playlist *p = collection->upcomingPlaylist();
action<KToggleAction>("saveUpcomingTracks")->setChecked(true);
s >> *p;
playlist = p;
collection->setUpcomingPlaylist(p);
*/
break;
}
case Folder:
......
......@@ -171,8 +171,8 @@ public:
virtual void refresh();
PlaylistItem *itemForPlaylist(const Playlist *playlist);
void updateCollectionDict(const QString &oldPath, const QString &newPath);
void repaint() const;
PlaylistItemList children() const { return m_children; }
protected:
CollectionListItem(const FileHandle &file);
......
......@@ -68,7 +68,7 @@
<Action name="toggleSystemTray" append="show_merge"/>
<Action name="dockOnClose" append="show_merge"/>
<Action name="togglePopups" append="show_merge"/>
<Action name="saveUpcomingTracks" append="show_merge"/>
<!-- <Action name="saveUpcomingTracks" append="show_merge"/> -->
<Action name="tagGuesserConfig" append="save_merge"/>
<Action name="fileRenamerConfig" append="save_merge"/>
<Action name="outputSelect" append="save_merge"/>
......
......@@ -70,7 +70,7 @@
<Action name="toggleSystemTray" append="show_merge"/>
<Action name="dockOnClose" append="show_merge"/>
<Action name="togglePopups" append="show_merge"/>
<Action name="saveUpcomingTracks" append="show_merge"/>
<!-- <Action name="saveUpcomingTracks" append="show_merge"/> -->
<Action name="tagGuesserConfig" append="save_merge"/>
<Action name="fileRenamerConfig" append="save_merge"/>
<Action name="outputSelect" append="save_merge"/>
......
......@@ -303,7 +303,6 @@ void Playlist::SharedSettings::writeConfig()
////////////////////////////////////////////////////////////////////////////////
PlaylistItemList Playlist::m_history;
UpcomingPlaylist *Playlist::m_upcomingPlaylist = 0;
QMap<int, PlaylistItem *> Playlist::m_backMenuItems;
int Playlist::m_leftColumn = 0;
......@@ -434,20 +433,22 @@ int Playlist::time() const
// Since this method gets a lot of traffic, let's optimize for such.
if(!m_addTime.isEmpty()) {
for(PlaylistItemList::ConstIterator it = m_addTime.begin();
for(QValueList<PlaylistItem::Pointer>::ConstIterator it = m_addTime.begin();
it != m_addTime.end(); ++it)
{
m_time += (*it)->file().tag()->seconds();
if(*it)
m_time += (*it)->file().tag()->seconds();
}
m_addTime.clear();
}
if(!m_subtractTime.isEmpty()) {
for(PlaylistItemList::ConstIterator it = m_subtractTime.begin();
for(QValueList<PlaylistItem::Pointer>::ConstIterator it = m_subtractTime.begin();
it != m_subtractTime.end(); ++it)
{
m_time -= (*it)->file().tag()->seconds();
if(*it)
m_time -= (*it)->file().tag()->seconds();
}
m_subtractTime.clear();
......@@ -1560,7 +1561,8 @@ void Playlist::setPlaying(PlaylistItem *item, bool addToHistory)
if(playingItem()) {
if(addToHistory) {
if(playingItem()->playlist() == m_upcomingPlaylist)
if(playingItem()->playlist() ==
playingItem()->playlist()->m_collection->upcomingPlaylist())
m_history.append(playingItem()->collectionItem());
else
m_history.append(playingItem());
......@@ -1901,7 +1903,7 @@ void Playlist::slotUpdateColumnWidths()
void Playlist::slotAddToUpcoming()
{
m_collection->setUpcomingPlaylistEnabled(true);
m_upcomingPlaylist->appendItems(selectedItems());
m_collection->upcomingPlaylist()->appendItems(selectedItems());
}
void Playlist::slotShowRMBMenu(QListViewItem *item, const QPoint &point, int column)
......
......@@ -28,6 +28,7 @@
#include "playlistsearch.h"
#include "tagguesser.h"
#include "playlistinterface.h"
#include "playlistitem.h"
class KPopupMenu;
class KActionMenu;
......@@ -36,14 +37,11 @@ class QEvent;
class PlaylistCollection;
class PlaylistItem;
class PlaylistToolTip;
class UpcomingPlaylist;
typedef QValueList<PlaylistItem *> PlaylistItemList;
typedef QValueList<Playlist *> PlaylistList;
class Playlist : public KListView, public PlaylistInterface
{
Q_OBJECT
......@@ -189,7 +187,7 @@ public:
* items since it has the overhead of checking to see if the file is a playlist
* or directory first.
*/
void addFiles(const QStringList &files, PlaylistItem *after = 0);
virtual void addFiles(const QStringList &files, PlaylistItem *after = 0);
/**
* Returns the file name associated with this playlist (an m3u file) or
......@@ -439,10 +437,6 @@ protected:
*/
virtual void polish();
UpcomingPlaylist *upcomingPlaylist() const { return m_upcomingPlaylist; }
void setUpcomingPlaylist(UpcomingPlaylist *playlist) { m_upcomingPlaylist = playlist; }
/**
* Do some finial initialization of created items. Notably ensure that they
* are shown or hidden based on the contents of the current PlaylistSearch.
......@@ -632,8 +626,8 @@ private:
bool m_disableColumnWidthUpdates;
mutable int m_time;
mutable PlaylistItemList m_addTime;
mutable PlaylistItemList m_subtractTime;
mutable QValueList<PlaylistItem::Pointer> m_addTime;
mutable QValueList<PlaylistItem::Pointer> m_subtractTime;
/**
* The average minimum widths of columns to be used in balancing calculations.
......@@ -675,7 +669,6 @@ private:
*/
static bool m_visibleChanged;
static int m_leftColumn;
static UpcomingPlaylist *m_upcomingPlaylist;
static QMap<int, PlaylistItem *> m_backMenuItems;
bool m_blockDataChanged;
......
......@@ -532,8 +532,6 @@ void PlaylistCollection::setUpcomingPlaylistEnabled(bool enable)
if(!m_upcomingPlaylist)
m_upcomingPlaylist = new UpcomingPlaylist(this);
m_upcomingPlaylist->initialize();
setupPlaylist(m_upcomingPlaylist, "today");
}
else {
......@@ -559,7 +557,7 @@ Playlist *PlaylistCollection::currentPlaylist() const
if(m_belowDistraction)
return m_belowDistraction;
if(m_upcomingPlaylist)
if(m_upcomingPlaylist && m_upcomingPlaylist->active())
return m_upcomingPlaylist;
if(Playlist::playingItem())
......
......@@ -114,13 +114,6 @@ public:
UpcomingPlaylist *upcomingPlaylist() const;
void setUpcomingPlaylistEnabled(bool enable);
/**
* Sets the playlist without initializing it (for use by Cache before GUI
* is completely setup). Call setUpcomingPlaylistEnabled(true) when the
* rest of initialization is ready.
*/
void setUpcomingPlaylist(UpcomingPlaylist *p) { m_upcomingPlaylist = p; }
void dirChanged(const QString &path);
/**
......
......@@ -183,6 +183,7 @@ private:
class PlaylistItem::Pointer
{
public:
Pointer() : m_item(0) {}
Pointer(PlaylistItem *item);
Pointer(const Pointer &p);
~Pointer();
......
......@@ -127,8 +127,10 @@ void TrackSequenceManager::setCurrent(PlaylistItem *item)
{
if(item != m_iterator->current()) {
m_iterator->setCurrent(item);
if(!item)
m_iterator->reset();
if(item)
setCurrentPlaylist(item->playlist());
else
m_iterator->reset();
}
}
......
......@@ -28,6 +28,7 @@ using namespace ActionCollection;
UpcomingPlaylist::UpcomingPlaylist(PlaylistCollection *collection, int defaultSize) :
Playlist(collection, true),
m_active(false),
m_oldIterator(0),
m_defaultSize(defaultSize)
{
......@@ -39,11 +40,15 @@ UpcomingPlaylist::UpcomingPlaylist(PlaylistCollection *collection, int defaultSi
UpcomingPlaylist::~UpcomingPlaylist()
{
removeIteratorOverride();
setUpcomingPlaylist(0);
}
void UpcomingPlaylist::initialize()
{
if(m_active)
return;
m_active = true;
m_oldIterator = manager()->takeIterator();
manager()->installIterator(new UpcomingSequenceIterator(this));
......@@ -51,27 +56,12 @@ void UpcomingPlaylist::initialize()
m_oldIterator->prepareToPlay(CollectionList::instance());
else
manager()->iterator()->setCurrent(m_oldIterator->current());
// If an item was already playing, then it will be the last item in the
// list instead of the first, so we'll need to move it after the list is
// initialized. Also, we should fill the list to our set number of items.
bool needsAdjusting = playingItem() != 0;
if(needsAdjusting && action<KToggleAction>("loopPlaylist")->isChecked()) {
m_oldIterator->advance();
fillList();
PlaylistItem *item = static_cast<PlaylistItem *>(lastItem());
takeItem(item);
insertItem(item);
setPlaying(item, false);
}
setUpcomingPlaylist(this);
}
void UpcomingPlaylist::appendItems(const PlaylistItemList &itemList)
{
initialize();
if(itemList.isEmpty())
return;
......@@ -88,21 +78,21 @@ void UpcomingPlaylist::appendItems(const PlaylistItemList &itemList)
void UpcomingPlaylist::playNext()
{
TrackSequenceManager::instance()->setCurrentPlaylist(this);
setPlaying(TrackSequenceManager::instance()->nextItem());
if(!playing())
return;
initialize();
Playlist *source = m_playlistIndex[playingItem()];
PlaylistItem *next = TrackSequenceManager::instance()->nextItem();
if(!source)
return;
PlaylistList l;
l.append(this);
source->synchronizePlayingItems(l, false);
if(next) {
setPlaying(next);
Playlist *source = m_playlistIndex[next];
if(source) {
PlaylistList l;
l.append(this);
source->synchronizePlayingItems(l, false);
}
}
else
removeIteratorOverride();
}
void UpcomingPlaylist::clearItem(PlaylistItem *item, bool emitChanged)
......@@ -111,85 +101,45 @@ void UpcomingPlaylist::clearItem(PlaylistItem *item, bool emitChanged)
Playlist::clearItem(item, emitChanged);
}
QMap< PlaylistItem *, QGuardedPtr<Playlist> > &UpcomingPlaylist::playlistIndex()
{
return m_playlistIndex;
}
void UpcomingPlaylist::removeIteratorOverride()
void UpcomingPlaylist::addFiles(const QStringList &files, PlaylistItem *after)
{
if(!m_oldIterator)
return;
CollectionList::instance()->addFiles(files, after);
PlaylistItem *newItem = 0;
if(playingItem())
newItem = playingItem()->collectionItem();
m_oldIterator->reset();
m_oldIterator->setCurrent(newItem);
manager()->setCurrent(newItem);
manager()->installIterator(m_oldIterator);
setPlaying(newItem, false);
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);
}
Watched::currentChanged();
appendItems(l);
}
void UpcomingPlaylist::fillList()
QMap< PlaylistItem::Pointer, QGuardedPtr<Playlist> > &UpcomingPlaylist::playlistIndex()
{
PlaylistItemList list;
int i = 0, limit = m_defaultSize - items().count();
if(!m_oldIterator->current())
m_oldIterator->prepareToPlay(CollectionList::instance());
if(!m_oldIterator->current())
return;
while(i++ < limit && m_oldIterator->current()) {
list.append(m_oldIterator->current());
m_oldIterator->advance();
}
createItems(list);
return m_playlistIndex;
}
void UpcomingPlaylist::addNewItem()
void UpcomingPlaylist::removeIteratorOverride()
{
PlaylistItem *last = static_cast<PlaylistItem *>(lastChild());
if(firstChild()) {
Playlist *source = m_playlistIndex[firstChild()];
if(!source)
return;
CollectionListItem *base = firstChild()->collectionItem();
PlaylistItem *target = 0;
for(QListViewItemIterator it(source); it.current(); ++it) {
if(static_cast<PlaylistItem *>(it.current())->collectionItem() == base) {
target = static_cast<PlaylistItem *>(it.current());
break;
}
}
if(!m_active)
return;
if(!target)
return;
m_active = false;
m_oldIterator->setCurrent(target);
m_oldIterator->advance();
}
if(!m_oldIterator || !playingItem())
return;
if(m_oldIterator->current()) {
last = createItem(m_oldIterator->current(), last);
m_playlistIndex.insert(last, m_oldIterator->current()->playlist());
dataChanged();
slotWeightDirty();
}
m_oldIterator->reset();
m_oldIterator->setCurrent(playingItem()->collectionItem());
manager()->installIterator(m_oldIterator);
manager()->nextItem();
setPlaying(manager()->nextItem(), true);
Watched::currentChanged();
}
inline TrackSequenceManager *UpcomingPlaylist::manager() const
TrackSequenceManager *UpcomingPlaylist::manager() const
{
return TrackSequenceManager::instance();
}
......@@ -213,16 +163,10 @@ void UpcomingPlaylist::UpcomingSequenceIterator::advance()
PlaylistItem *item = m_playlist->firstChild();
if(item) {
if(!item->nextSibling())
m_playlist->addNewItem();
m_playlist->setPlaying(0);
PlaylistItem *next = static_cast<PlaylistItem *>(item->nextSibling());
m_playlist->clearItem(item);
setCurrent(next);
}
else
m_playlist->fillList();
setCurrent(m_playlist->firstChild());
}
void UpcomingPlaylist::UpcomingSequenceIterator::backup()
......@@ -245,12 +189,8 @@ void UpcomingPlaylist::UpcomingSequenceIterator::setCurrent(PlaylistItem *curren
// apparently the user didn't want to hear it.
PlaylistItem *playingItem = m_playlist->playingItem();
if(playingItem && playingItem->playlist() == m_playlist && currentItem != playingItem) {
if(action<KToggleAction>("loopPlaylist")->isChecked())
m_playlist->addNewItem();
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
......@@ -263,9 +203,9 @@ void UpcomingPlaylist::UpcomingSequenceIterator::setCurrent(PlaylistItem *curren
m_playlist->slotWeightDirty();
}
else {
// if(p == m_playlist) {
// Bump this item up to the top
m_playlist->takeItem(currentItem);
m_playlist->insertItem(currentItem);
}
......@@ -280,9 +220,8 @@ void UpcomingPlaylist::UpcomingSequenceIterator::reset()
void UpcomingPlaylist::UpcomingSequenceIterator::prepareToPlay(Playlist *)
{
if(m_playlist->items().isEmpty())
m_playlist->fillList();
setCurrent(m_playlist->firstChild());
if(!m_playlist->items().isEmpty())
setCurrent(m_playlist->firstChild());
}
QDataStream &operator<<(QDataStream &s, const UpcomingPlaylist &p)
......
......@@ -90,12 +90,16 @@ public:
*/
virtual void clearItem(PlaylistItem *item, bool emitChanged = true);
virtual void addFiles(const QStringList &files, PlaylistItem *after = 0);
/**
* Returns a reference to the index between items in the list and the
* playlist that they came from. This is used to remap the currently
* playing item to the source playlist.
*/
QMap< PlaylistItem *, QGuardedPtr<Playlist> > &playlistIndex();
QMap<PlaylistItem::Pointer, QGuardedPtr<Playlist> > &playlistIndex();
bool active() const { return m_active; }
private:
......@@ -106,34 +110,22 @@ private:
*/
void removeIteratorOverride();
/**
* This function fills the playlist up to a certain number of items. This
* is useful for when the user clicks on play even when the playlist is
* empty.
*/
void fillList();
/**
* This function appends another item to the end of the playlist, based on
* the old TrackSequenceManager iterator.
*/
void addNewItem();
/**
* This function returns the instance of the TrackSequenceManager.
*
* @return the TrackSequenceManager instance.
* @see TrackSequenceManager::instance()
*/
inline TrackSequenceManager *manager() const;
TrackSequenceManager *manager() const;
private:
class UpcomingSequenceIterator;
friend class UpcomingSequenceIterator;
bool m_active;
TrackSequenceIterator *m_oldIterator;
int m_defaultSize;
QMap< PlaylistItem *, QGuardedPtr<Playlist> > m_playlistIndex;
QMap<PlaylistItem::Pointer, QGuardedPtr<Playlist> > m_playlistIndex;
};
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment