mirror of
https://github.com/clementine-player/Clementine
synced 2025-02-02 12:26:48 +01:00
parent
d15fffc802
commit
85d5e398da
@ -689,7 +689,8 @@ void MainWindow::SetCurrentPlaylist(PlaylistView* pCurrent){
|
||||
current_playlist_view_ = pCurrent ;
|
||||
current_playlist_ = qobject_cast< Playlist* >( pCurrent->model() );
|
||||
player_->SetCurrentPlaylist(current_playlist_);
|
||||
|
||||
|
||||
current_playlist_->set_shuffle_repeat_widget(shuffle_repeat_widget_);
|
||||
|
||||
// connects !! :)
|
||||
|
||||
@ -709,6 +710,9 @@ void MainWindow::SetCurrentPlaylist(PlaylistView* pCurrent){
|
||||
connect(player_, SIGNAL(Stopped()), current_playlist_view_, SLOT(StopGlowing()));
|
||||
|
||||
connect(radio_model_, SIGNAL(StreamMetadataFound(QUrl,Song)), current_playlist_, SLOT(SetStreamMetadata(QUrl,Song)));
|
||||
|
||||
connect(shuffle_repeat_widget_, SIGNAL(ShuffleModeChanged(ShuffleRepeatWidget::ShuffleMode)),
|
||||
current_playlist_, SLOT(ShuffleModeChanged(ShuffleRepeatWidget::ShuffleMode)));
|
||||
}
|
||||
|
||||
void MainWindow::CurrentTabChanged(int index ){
|
||||
|
124
src/playlist.cpp
124
src/playlist.cpp
@ -14,6 +14,7 @@
|
||||
#include <QDirIterator>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#include <lastfm/ScrobblePoint>
|
||||
|
||||
@ -23,11 +24,14 @@ const char* Playlist::kSettingsGroup = "Playlist";
|
||||
Playlist::Playlist(QObject *parent) :
|
||||
QAbstractListModel(parent),
|
||||
current_is_paused_(false),
|
||||
current_virtual_index_(-1),
|
||||
is_shuffled_(false),
|
||||
scrobble_point_(-1),
|
||||
has_scrobbled_(false),
|
||||
ignore_sorting_(false),
|
||||
title_(""),
|
||||
index_(-1)
|
||||
index_(-1),
|
||||
shuffle_repeat_widget_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -111,14 +115,68 @@ int Playlist::current_index() const {
|
||||
return current_item_.isValid() ? current_item_.row() : -1;
|
||||
}
|
||||
|
||||
void Playlist::ShuffleModeChanged(ShuffleRepeatWidget::ShuffleMode mode) {
|
||||
is_shuffled_ = (mode != ShuffleRepeatWidget::Shuffle_Off);
|
||||
ReshuffleIndices();
|
||||
}
|
||||
|
||||
int Playlist::NextVirtualIndex(int i) const {
|
||||
ShuffleRepeatWidget::RepeatMode repeat_mode = shuffle_repeat_widget_->repeat_mode();
|
||||
ShuffleRepeatWidget::ShuffleMode shuffle_mode = shuffle_repeat_widget_->shuffle_mode();
|
||||
bool album_only = repeat_mode == ShuffleRepeatWidget::Repeat_Album ||
|
||||
shuffle_mode == ShuffleRepeatWidget::Shuffle_Album;
|
||||
|
||||
// This one's easy - if we have to repeat the current track then just return i
|
||||
if (repeat_mode == ShuffleRepeatWidget::Repeat_Track)
|
||||
return i;
|
||||
|
||||
// If we're not bothered about whether a song is on the same album then
|
||||
// return the next virtual index, whatever it is.
|
||||
if (!album_only)
|
||||
return i+1;
|
||||
|
||||
// We need to advance i until we get something else on the same album
|
||||
Song last_song = current_item_metadata();
|
||||
for (int j=i+1 ; j<virtual_items_.count(); ++j) {
|
||||
Song this_song = item_at(virtual_items_[j])->Metadata();
|
||||
if ((last_song.is_compilation() && this_song.is_compilation() ||
|
||||
last_song.artist() == this_song.artist()) &&
|
||||
last_song.album() == this_song.album()) {
|
||||
return j; // Found one
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find one - return past the end of the list
|
||||
return virtual_items_.count();
|
||||
}
|
||||
|
||||
int Playlist::next_index() const {
|
||||
int i = current_index() + 1;
|
||||
if (i >= items_.count())
|
||||
return -1;
|
||||
// Did we want to stop after this track?
|
||||
if (stop_after_.isValid() && current_index() == stop_after_.row())
|
||||
return -1;
|
||||
|
||||
return i;
|
||||
int next_virtual_index = NextVirtualIndex(current_virtual_index_);
|
||||
if (next_virtual_index >= virtual_items_.count()) {
|
||||
// We've gone off the end of the playlist.
|
||||
|
||||
switch (shuffle_repeat_widget_->repeat_mode()) {
|
||||
case ShuffleRepeatWidget::Repeat_Off:
|
||||
return -1;
|
||||
case ShuffleRepeatWidget::Repeat_Track:
|
||||
next_virtual_index = current_virtual_index_;
|
||||
break;
|
||||
|
||||
default:
|
||||
next_virtual_index = NextVirtualIndex(-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Still off the end? Then just give up
|
||||
if (next_virtual_index >= virtual_items_.count())
|
||||
return -1;
|
||||
|
||||
return virtual_items_[next_virtual_index];
|
||||
}
|
||||
|
||||
int Playlist::previous_index() const {
|
||||
@ -142,6 +200,23 @@ void Playlist::set_current_index(int i) {
|
||||
emit CurrentSongChanged(current_item_metadata());
|
||||
}
|
||||
|
||||
// Update the virtual index
|
||||
if (i == -1)
|
||||
current_virtual_index_ = -1;
|
||||
else if (is_shuffled_ && current_virtual_index_ == -1) {
|
||||
// This is the first thing we're playing so we want to make sure the array
|
||||
// is shuffled
|
||||
ReshuffleIndices();
|
||||
|
||||
// Bring the one we've been asked to play to the start of the list
|
||||
virtual_items_.takeAt(virtual_items_.indexOf(i));
|
||||
virtual_items_.prepend(i);
|
||||
current_virtual_index_ = 0;
|
||||
} else if (is_shuffled_)
|
||||
current_virtual_index_ = virtual_items_.indexOf(i);
|
||||
else
|
||||
current_virtual_index_ = i;
|
||||
|
||||
UpdateScrobblePoint();
|
||||
}
|
||||
|
||||
@ -275,14 +350,14 @@ QModelIndex Playlist::InsertItems(const QList<PlaylistItem*>& items, int after)
|
||||
const int end = start + items.count() - 1;
|
||||
|
||||
beginInsertRows(QModelIndex(), start, end);
|
||||
|
||||
for (int i=start ; i<=end ; ++i) {
|
||||
items_.insert(i, items[i - start]);
|
||||
virtual_items_ << virtual_items_.count();
|
||||
}
|
||||
|
||||
endInsertRows();
|
||||
|
||||
// Save();
|
||||
ReshuffleIndices();
|
||||
|
||||
return index(start, 0);
|
||||
}
|
||||
@ -428,6 +503,7 @@ void Playlist::SaveR() const {
|
||||
void Playlist::RestoreR() {
|
||||
qDeleteAll(items_);
|
||||
items_.clear();
|
||||
virtual_items_.clear();
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
@ -444,6 +520,7 @@ void Playlist::RestoreR() {
|
||||
|
||||
item->Restore(s);
|
||||
items_ << item;
|
||||
virtual_items_ << virtual_items_.count();
|
||||
}
|
||||
s.endArray();
|
||||
s.endGroup();
|
||||
@ -460,6 +537,20 @@ bool Playlist::removeRows(int row, int count, const QModelIndex& parent) {
|
||||
|
||||
endRemoveRows();
|
||||
|
||||
QList<int>::iterator it = virtual_items_.begin();
|
||||
int i = 0;
|
||||
while (it != virtual_items_.end()) {
|
||||
if (*it >= items_.count()) {
|
||||
if (i >= current_virtual_index_)
|
||||
current_virtual_index_ --;
|
||||
|
||||
it = virtual_items_.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
// Save();
|
||||
return true;
|
||||
}
|
||||
@ -582,3 +673,22 @@ void Playlist::Shuffle() {
|
||||
|
||||
// Save();
|
||||
}
|
||||
|
||||
void Playlist::ReshuffleIndices() {
|
||||
if (!is_shuffled_) {
|
||||
std::sort(virtual_items_.begin(), virtual_items_.end());
|
||||
if (current_index() != -1)
|
||||
current_virtual_index_ = virtual_items_.indexOf(current_index());
|
||||
} else {
|
||||
QList<int>::iterator begin = virtual_items_.begin();
|
||||
if (current_virtual_index_ != -1)
|
||||
std::advance(begin, current_virtual_index_ + 1);
|
||||
|
||||
std::random_shuffle(begin, virtual_items_.end());
|
||||
}
|
||||
}
|
||||
|
||||
void Playlist::set_shuffle_repeat_widget(ShuffleRepeatWidget* w) {
|
||||
shuffle_repeat_widget_ = w;
|
||||
ShuffleModeChanged(w->shuffle_mode());
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "playlistitem.h"
|
||||
#include "song.h"
|
||||
#include "radioitem.h"
|
||||
#include "shufflerepeatwidget.h"
|
||||
|
||||
class RadioService;
|
||||
|
||||
@ -72,7 +73,10 @@ class Playlist : public QAbstractListModel {
|
||||
void SetTitle(const QString& title) { title_ = title; }
|
||||
|
||||
void SetPlaylistIndex( int ipos ) { index_ = ipos ; }
|
||||
int GetPlaylistIndex() const { return index_ ; }
|
||||
int GetPlaylistIndex() const { return index_ ; }
|
||||
|
||||
void set_shuffle_repeat_widget(ShuffleRepeatWidget* w);
|
||||
ShuffleRepeatWidget* shuffle_repeat_widget() const { return shuffle_repeat_widget_; }
|
||||
|
||||
// Scrobbling
|
||||
int scrobble_point() const { return scrobble_point_; }
|
||||
@ -114,12 +118,16 @@ class Playlist : public QAbstractListModel {
|
||||
void Clear();
|
||||
void Shuffle();
|
||||
|
||||
void ShuffleModeChanged(ShuffleRepeatWidget::ShuffleMode mode);
|
||||
|
||||
signals:
|
||||
void CurrentSongChanged(const Song& metadata);
|
||||
|
||||
private:
|
||||
void SetCurrentIsPaused(bool paused);
|
||||
void UpdateScrobblePoint();
|
||||
void ReshuffleIndices();
|
||||
int NextVirtualIndex(int i) const;
|
||||
|
||||
// Persistence
|
||||
void SaveR() const;
|
||||
@ -127,10 +135,14 @@ class Playlist : public QAbstractListModel {
|
||||
|
||||
private:
|
||||
QList<PlaylistItem*> items_;
|
||||
QList<int> virtual_items_; // Contains the indices into items_ in the order
|
||||
// that they will be played.
|
||||
bool is_shuffled_;
|
||||
|
||||
QPersistentModelIndex current_item_;
|
||||
QPersistentModelIndex stop_after_;
|
||||
bool current_is_paused_;
|
||||
int current_virtual_index_;
|
||||
|
||||
int scrobble_point_;
|
||||
bool has_scrobbled_;
|
||||
@ -138,7 +150,9 @@ class Playlist : public QAbstractListModel {
|
||||
// Hack to stop QTreeView::setModel sorting the playlist
|
||||
bool ignore_sorting_;
|
||||
QString title_;
|
||||
int index_ ;
|
||||
int index_ ;
|
||||
|
||||
ShuffleRepeatWidget* shuffle_repeat_widget_;
|
||||
};
|
||||
|
||||
#endif // PLAYLIST_H
|
||||
|
@ -3,10 +3,10 @@
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QMenu;
|
||||
|
||||
#include "ui_shufflerepeatwidget.h"
|
||||
|
||||
class QMenu;
|
||||
|
||||
class ShuffleRepeatWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
@ -27,21 +27,25 @@ class ShuffleRepeatWidget : public QWidget {
|
||||
|
||||
static const char* kSettingsGroup;
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
RepeatMode repeat_mode() const { return repeat_mode_; }
|
||||
ShuffleMode shuffle_mode() const { return shuffle_mode_; }
|
||||
|
||||
public slots:
|
||||
void SetRepeatMode(RepeatMode mode);
|
||||
void SetShuffleMode(ShuffleMode mode);
|
||||
void SetRepeatMode(ShuffleRepeatWidget::RepeatMode mode);
|
||||
void SetShuffleMode(ShuffleRepeatWidget::ShuffleMode mode);
|
||||
|
||||
signals:
|
||||
void RepeatModeChanged(RepeatMode mode);
|
||||
void ShuffleModeChanged(ShuffleMode mode);
|
||||
void RepeatModeChanged(ShuffleRepeatWidget::RepeatMode mode);
|
||||
void ShuffleModeChanged(ShuffleRepeatWidget::ShuffleMode mode);
|
||||
|
||||
private slots:
|
||||
void RepeatActionTriggered(QAction*);
|
||||
void ShuffleActionTriggered(QAction*);
|
||||
|
||||
private:
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
private:
|
||||
Ui::ShuffleRepeatWidget ui_;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user