File indexing completed on 2024-05-19 04:49:50
0001 /**************************************************************************************** 0002 * Copyright (c) 2008 Seb Ruiz <ruiz@kde.org> * 0003 * Copyright (c) 2008 Soren Harward <stharward@gmail.com> * 0004 * Copyright (c) 2008 Nikolaj Hald Nielsen <nhn@kde.org> * 0005 * Copyright (c) 2009 Téo Mrnjavac <teo@kde.org> * 0006 * Copyright (c) 2010 Nanno Langstraat <langstr@gmail.com> * 0007 * Copyright (c) 2013 Daniel Schmitz <daniel.schmitz@gmx.info> * 0008 * * 0009 * This program is free software; you can redistribute it and/or modify it under * 0010 * the terms of the GNU General Public License as published by the Free Software * 0011 * Foundation; either version 2 of the License, or (at your option) version 3 or * 0012 * any later version accepted by the membership of KDE e.V. (or its successor approved * 0013 * by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of * 0014 * version 3 of the license. * 0015 * * 0016 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0017 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0018 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License along with * 0021 * this program. If not, see <http://www.gnu.org/licenses/>. * 0022 ****************************************************************************************/ 0023 0024 #define DEBUG_PREFIX "Playlist::RandomTrackNavigator" 0025 0026 #include "RandomTrackNavigator.h" 0027 0028 #include "core/support/Debug.h" 0029 0030 #include <QDateTime> 0031 #include <QRandomGenerator> // For 'QRandomGenerator::global()->generate()' 0032 0033 #include <cmath> // For 'round()' 0034 0035 Playlist::RandomTrackNavigator::RandomTrackNavigator() 0036 { 0037 loadFromSourceModel(); 0038 } 0039 0040 void 0041 Playlist::RandomTrackNavigator::planOne() 0042 { 0043 DEBUG_BLOCK 0044 0045 if ( m_plannedItems.isEmpty() ) 0046 { 0047 if ( !allItemsList().isEmpty() ) 0048 { 0049 quint64 chosenItem; 0050 0051 int avoidRecentlyPlayedSize = AVOID_RECENTLY_PLAYED_MAX; // Start with being very picky. 0052 0053 // Don't over-constrain ourself: 0054 // - Keep enough headroom to be unpredictable. 0055 // - Make sure that 'chooseRandomItem()' doesn't need to find a needle in a haystack. 0056 avoidRecentlyPlayedSize = qMin( avoidRecentlyPlayedSize, allItemsList().size() / 2 ); 0057 0058 QSet<quint64> avoidSet = getRecentHistory( avoidRecentlyPlayedSize ); 0059 chosenItem = chooseRandomItem( avoidSet ); 0060 0061 m_plannedItems.append( chosenItem ); 0062 } 0063 } 0064 } 0065 0066 QSet<quint64> 0067 Playlist::RandomTrackNavigator::getRecentHistory( int size ) 0068 { 0069 QList<quint64> allHistory = historyItems(); 0070 QSet<quint64> recentHistory; 0071 0072 if ( size > 0 ) { // If '== 0', we even need to consider playing the same item again. 0073 recentHistory.insert( currentItem() ); // Might be '0' 0074 size--; 0075 } 0076 0077 for ( int i = allHistory.size() - 1; ( i >= 0 ) && ( i >= allHistory.size() - size ); i-- ) 0078 recentHistory.insert( allHistory.at( i ) ); 0079 0080 return recentHistory; 0081 } 0082 0083 quint64 0084 Playlist::RandomTrackNavigator::chooseRandomItem( const QSet<quint64> &avoidSet ) 0085 { 0086 quint64 chosenItem; 0087 0088 do 0089 { 0090 int maxPosition = allItemsList().size() - 1; 0091 int randomPosition = round( ( QRandomGenerator::global()->generate() / (float)RAND_MAX ) * maxPosition ); 0092 chosenItem = allItemsList().at( randomPosition ); 0093 } while ( avoidSet.contains( chosenItem ) ); 0094 0095 return chosenItem; 0096 }