Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Multimedia
JuK
Commits
b1097f4e
Commit
b1097f4e
authored
Mar 22, 2021
by
Michael Pyne
Browse files
playlist: Reimplement random and album random sequencing.
parent
6aef3be8
Changes
2
Hide whitespace changes
Inline
Side-by-side
playlist.cpp
View file @
b1097f4e
...
...
@@ -64,6 +64,7 @@
#include <time.h>
#include <cmath>
#include <algorithm>
#include <random>
#include "directoryloader.h"
#include "playlistitem.h"
...
...
@@ -122,10 +123,24 @@ Playlist::Playlist(
:
QTreeWidget
(
collection
->
playlistStack
())
,
m_collection
(
collection
)
,
m_playlistName
(
name
)
,
m_refillDebounce
(
new
QTimer
(
this
))
,
m_fetcher
(
new
WebImageFetcher
(
this
))
{
setup
(
extraCols
);
// The timer soaks up repeated events that may cause the random play list
// to be regenerated repeatedly.
m_refillDebounce
->
setInterval
(
100
);
m_refillDebounce
->
setSingleShot
(
true
);
connect
(
m_refillDebounce
,
&
QTimer
::
timeout
,
this
,
&
Playlist
::
refillRandomList
);
// Any of the random-related actions being triggered will cause the parent
// group to emit the triggered signal.
QActionGroup
*
randomGroup
=
action
(
"disableRandomPlay"
)
->
actionGroup
();
connect
(
randomGroup
,
&
QActionGroup
::
triggered
,
m_refillDebounce
,
qOverload
<>
(
&
QTimer
::
start
));
// Some subclasses need to do even more handling but will remember to
// call setupPlaylist
if
(
!
delaySetup
)
{
...
...
@@ -174,6 +189,7 @@ Playlist::~Playlist()
// make clear that it's intentional that those subclassed versions don't
// get called (because we can't call them)
m_randomSequence
.
clear
();
Playlist
::
clearItems
(
Playlist
::
items
());
if
(
!
m_shuttingDown
)
...
...
@@ -197,26 +213,82 @@ void Playlist::playFirst()
{
QTreeWidgetItemIterator
listIt
(
const_cast
<
Playlist
*>
(
this
),
QTreeWidgetItemIterator
::
NotHidden
);
beginPlayingItem
(
static_cast
<
PlaylistItem
*>
(
*
listIt
));
refillRandomList
();
}
void
Playlist
::
playNextAlbum
()
{
#if 0
#else
playNext
();
#endif
const
auto
&
item
=
playingItem
();
if
(
!
item
||
!
action
(
"albumRandomPlay"
)
->
isChecked
())
{
playNext
();
return
;
}
const
auto
currentAlbum
=
item
->
file
().
tag
()
->
album
();
const
auto
nextAlbumTrack
=
std
::
find_if
(
m_randomSequence
.
begin
(),
m_randomSequence
.
end
(),
[
currentAlbum
](
const
PlaylistItem
*
item
)
{
return
item
->
file
().
tag
()
->
album
()
!=
currentAlbum
;
});
if
(
nextAlbumTrack
==
m_randomSequence
.
end
())
{
// We were on the last album, playNext will handle looping if we should loop
m_randomSequence
.
clear
();
playNext
();
}
else
{
m_randomSequence
.
erase
(
m_randomSequence
.
begin
(),
nextAlbumTrack
);
beginPlayingItem
(
*
nextAlbumTrack
);
}
}
void
Playlist
::
playNext
()
{
auto
nowPlaying
=
playingItem
();
QTreeWidgetItemIterator
listIt
(
nowPlaying
,
QTreeWidgetItemIterator
::
NotHidden
);
PlaylistItem
*
next
=
nullptr
;
if
(
*
listIt
)
{
++
listIt
;
auto
nowPlaying
=
playingItem
();
bool
doLoop
=
action
(
"loopPlaylist"
)
->
isChecked
();
// Treat an item from a different playlist as if we were being asked to
// play from a stop
if
(
nowPlaying
&&
nowPlaying
->
playlist
()
!=
this
)
{
nowPlaying
=
nullptr
;
}
if
(
action
(
"disableRandomPlay"
)
->
isChecked
())
{
QTreeWidgetItemIterator
listIt
=
nowPlaying
?
QTreeWidgetItemIterator
(
nowPlaying
,
QTreeWidgetItemIterator
::
NotHidden
)
:
QTreeWidgetItemIterator
(
this
,
QTreeWidgetItemIterator
::
NotHidden
);
if
(
*
listIt
&&
nowPlaying
)
{
++
listIt
;
}
next
=
static_cast
<
PlaylistItem
*>
(
*
listIt
);
if
(
!
next
&&
doLoop
)
{
playFirst
();
return
;
}
}
else
{
// The two random play modes are identical here, the difference is in how the
// randomized sequence is generated by refillRandomList
if
(
m_randomSequence
.
isEmpty
()
&&
(
doLoop
||
!
nowPlaying
))
{
refillRandomList
();
// Don't play the same track twice in a row even if it can
// "randomly" happen
if
(
m_randomSequence
.
front
()
==
nowPlaying
)
{
std
::
swap
(
m_randomSequence
.
front
(),
m_randomSequence
.
back
());
}
}
if
(
!
m_randomSequence
.
isEmpty
())
{
next
=
m_randomSequence
.
takeFirst
();
}
}
// Will stop playback if next is still null
beginPlayingItem
(
next
);
}
...
...
@@ -298,7 +370,7 @@ void Playlist::saveAs()
void
Playlist
::
updateDeletedItem
(
PlaylistItem
*
item
)
{
m_members
.
remove
(
item
->
file
().
absFilePath
());
m_randomSequence
.
removeAll
(
item
);
m_history
.
removeAll
(
item
);
}
...
...
@@ -509,7 +581,8 @@ void Playlist::slotBeginPlayback()
PlaylistItem
*
item
=
static_cast
<
PlaylistItem
*>
(
*
visible
);
if
(
item
)
{
beginPlayingItem
(
item
);
refillRandomList
();
playNext
();
}
else
{
action
(
"stop"
)
->
trigger
();
...
...
@@ -586,7 +659,7 @@ void Playlist::slotAddCover(bool retrieveLocal)
// Called when image fetcher has added a new cover.
void
Playlist
::
slotCoverChanged
(
int
coverId
)
{
qCDebug
(
JUK_LOG
)
<<
"Refreshing information for newly changed covers.
\n
"
;
qCDebug
(
JUK_LOG
)
<<
"Refreshing information for newly changed covers."
;
refreshAlbums
(
selectedItems
(),
coverId
);
}
...
...
@@ -626,6 +699,36 @@ void Playlist::slotReload()
loadFile
(
m_fileName
,
fileInfo
);
}
void
Playlist
::
refillRandomList
()
{
qCDebug
(
JUK_LOG
)
<<
"Refilling random items."
;
if
(
action
(
"disableRandomPlay"
)
->
isChecked
())
{
m_randomSequence
.
clear
();
return
;
}
PlaylistItemList
randomItems
=
visibleItems
();
// See https://www.pcg-random.org/posts/cpp-seeding-surprises.html
std
::
random_device
rdev
;
uint64_t
rseed
=
(
uint64_t
(
rdev
())
<<
32
)
|
rdev
();
std
::
linear_congruential_engine
<
uint64_t
,
6364136223846793005U
,
1442695040888963407U
,
0U
>
knuth_lcg
(
rseed
);
std
::
shuffle
(
randomItems
.
begin
(),
randomItems
.
end
(),
knuth_lcg
);
if
(
action
(
"albumRandomPlay"
)
->
isChecked
())
{
std
::
sort
(
randomItems
.
begin
(),
randomItems
.
end
(),
[](
PlaylistItem
*
a
,
PlaylistItem
*
b
)
{
return
a
->
file
().
tag
()
->
album
()
<
b
->
file
().
tag
()
->
album
();
});
}
std
::
swap
(
m_randomSequence
,
randomItems
);
}
void
Playlist
::
slotWeightDirty
(
int
column
)
{
if
(
column
<
0
)
{
...
...
@@ -738,6 +841,7 @@ void Playlist::removeFromDisk(const PlaylistItemList &items)
void
Playlist
::
synchronizeItemsTo
(
const
PlaylistItemList
&
itemList
)
{
// direct call to ::items to avoid infinite loop, bug 402355
m_randomSequence
.
clear
();
clearItems
(
Playlist
::
items
());
createItems
(
itemList
);
}
...
...
@@ -1667,11 +1771,12 @@ void Playlist::cleanupAfterAllFileLoadsCompleted()
// and let user adjust from there.
if
(
manualResize
())
{
auto
manualResizeAction
=
action
<
KToggleAction
>
(
"resizeColumnsManually"
);
auto
wasChecked
=
manualResizeAction
->
isChecked
();
manualResizeAction
->
toggle
(
);
manualResizeAction
->
setChecked
(
false
);
calculateColumnWeights
();
slotUpdateColumnWidths
();
manualResizeAction
->
toggle
(
);
manualResizeAction
->
setChecked
(
wasChecked
);
}
playlistItemsChanged
();
...
...
@@ -2089,6 +2194,7 @@ void Playlist::slotPlayCurrent()
QTreeWidgetItemIterator
it
(
this
,
QTreeWidgetItemIterator
::
Selected
);
PlaylistItem
*
next
=
static_cast
<
PlaylistItem
*>
(
*
it
);
beginPlayingItem
(
next
);
refillRandomList
();
}
void
Playlist
::
slotUpdateTime
()
...
...
playlist.h
View file @
b1097f4e
...
...
@@ -34,9 +34,10 @@
class
KActionMenu
;
class
QAction
;
class
QFileInfo
;
class
QMimeData
;
class
Q
Action
;
class
Q
Timer
;
class
WebImageFetcher
;
class
PlaylistItem
;
...
...
@@ -405,6 +406,12 @@ public slots:
*/
virtual
void
slotReload
();
/**
* Ensures the random sequence of playlist items is built. Ignored if we're
* not in random playback mode so it is safe to call in any mode.
*/
void
refillRandomList
();
/**
* Tells the listview that the next time that it paints that the weighted
* column widths must be recalculated. If this is called without a column
...
...
@@ -685,6 +692,10 @@ private:
bool
m_widthsDirty
=
true
;
bool
m_applySharedSettings
=
true
;
/// Used for random play and album random play
PlaylistItemList
m_randomSequence
;
QTimer
*
m_refillDebounce
;
PlaylistSearch
*
m_search
;
bool
m_searchEnabled
=
true
;
...
...
Michael Pyne
@mpyne
mentioned in commit
e8e5ef92
·
Mar 25, 2021
mentioned in commit
e8e5ef92
mentioned in commit e8e5ef9246a26f37b6430f33279b65cc1cf1771d
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment