File indexing completed on 2024-05-19 04:49:50
0001 /**************************************************************************************** 0002 * Copyright (c) 2007 Ian Monroe <ian@monroe.nu> * 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) 2011 Sandeep Raghuraman <sandy.8925@gmail.com> * 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 #include "StandardTrackNavigator.h" 0025 0026 #include "amarokconfig.h" 0027 #include "core/meta/Meta.h" 0028 #include "core/support/Amarok.h" 0029 #include "playlist/PlaylistModelStack.h" 0030 0031 Playlist::StandardTrackNavigator::StandardTrackNavigator() 0032 { 0033 m_repeatPlaylist = ( AmarokConfig::trackProgression() == AmarokConfig::EnumTrackProgression::RepeatPlaylist ); 0034 m_onlyQueue = ( AmarokConfig::trackProgression() == AmarokConfig::EnumTrackProgression::OnlyQueue ); 0035 } 0036 0037 quint64 0038 Playlist::StandardTrackNavigator::chooseLastTrack( bool repeatPlaylist ) 0039 { 0040 Meta::TrackPtr track; 0041 bool playableTrackFound = false; 0042 int lastRow; 0043 0044 // reminder: if that function is modified, it's important to research if changes must also 0045 // be applied to similar code in `Playlist::StandardTrackNavigator::chooseNextTrack()` 0046 0047 // search for a playable track in order from right before the currently active track till the start 0048 for ( lastRow = m_model->activeRow() - 1 ; lastRow >= 0 ; lastRow-- ) // 'activeRow()' may be -1 0049 { 0050 track = m_model->trackAt(lastRow); 0051 if ( track->isPlayable() ) 0052 { 0053 playableTrackFound = true; 0054 break; 0055 } 0056 } 0057 0058 // Even though the user is explicitly asking us to go back, still only do wrap-around 0059 // in mode 'm_repeatPlaylist'. Reason: many users of the standard navigator like to 0060 // move to the start of the playlist by blindly pressing "Prev" a lot of times. 0061 // If no playable track was found, the playlist needs to be repeated, it's not empty 0062 // and there's an active track: search from end of playlist till currently active track. 0063 if ( !playableTrackFound && repeatPlaylist && m_model->qaim()->rowCount() > 0 && m_model->activeRow() >= 0) 0064 { 0065 for ( lastRow = m_model->qaim()->rowCount() - 1 ; lastRow >= m_model->activeRow() ; lastRow--) 0066 { 0067 track = m_model->trackAt( lastRow ); 0068 if ( track->isPlayable() ) 0069 { 0070 playableTrackFound = true; 0071 break; 0072 } 0073 } 0074 } 0075 0076 if ( playableTrackFound && m_model->rowExists( lastRow ) ) 0077 return m_model->idAt( lastRow ); 0078 else 0079 return 0; 0080 } 0081 0082 quint64 0083 Playlist::StandardTrackNavigator::requestNextTrack() 0084 { 0085 if( !m_queue.isEmpty() ) { 0086 quint64 ret = m_queue.takeFirst(); 0087 Playlist::ModelStack::instance()->bottom()->emitQueueChanged(); 0088 return ret; 0089 } 0090 0091 return chooseNextTrack( m_repeatPlaylist ); 0092 } 0093 0094 quint64 0095 Playlist::StandardTrackNavigator::requestUserNextTrack() 0096 { 0097 if( !m_queue.isEmpty() ) { 0098 quint64 ret = m_queue.takeFirst(); 0099 Playlist::ModelStack::instance()->bottom()->emitQueueChanged(); 0100 return ret; 0101 } 0102 0103 // Don't make wrap-around conditional on 'm_repeatPlaylist': the user is explicitly asking for this. 0104 return chooseNextTrack( true ); 0105 } 0106 0107 quint64 0108 Playlist::StandardTrackNavigator::requestLastTrack() 0109 { 0110 if( !m_queue.isEmpty() ) { 0111 quint64 ret = m_queue.takeFirst(); 0112 Playlist::ModelStack::instance()->bottom()->emitQueueChanged(); 0113 return ret; 0114 } 0115 0116 return chooseLastTrack( m_repeatPlaylist ); 0117 } 0118 0119 quint64 0120 Playlist::StandardTrackNavigator::chooseNextTrack( bool repeatPlaylist ) 0121 { 0122 if( !m_queue.isEmpty() ) 0123 return m_queue.first(); 0124 0125 if( m_onlyQueue ) 0126 return 0; 0127 0128 Meta::TrackPtr track; 0129 bool playableTrackFound = false; 0130 int nextRow; 0131 0132 // reminder: if that function is modified, it's important to research if changes must also 0133 // be applied to similar code in `Playlist::StandardTrackNavigator::chooseLastTrack()` 0134 0135 //search for a playable track in order from right after the currently active track till the end 0136 for( nextRow = m_model->activeRow() + 1 ; nextRow < m_model->qaim()->rowCount() ; nextRow++ ) // 'activeRow()' may be -1. 0137 { 0138 track = m_model->trackAt(nextRow); 0139 if( track->isPlayable() ) 0140 { 0141 playableTrackFound = true; 0142 break; 0143 } 0144 } 0145 0146 //if no playable track was found and the playlist needs to be repeated, search from top of playlist till currently active track 0147 if( !playableTrackFound && repeatPlaylist ) 0148 { 0149 //nextRow=0; This row is still invalid if 'rowCount() == 0'. 0150 for( nextRow = 0 ; nextRow <= m_model->activeRow() ; nextRow++) 0151 { 0152 track = m_model->trackAt( nextRow ); 0153 if( track->isPlayable() ) 0154 { 0155 playableTrackFound = true; 0156 break; 0157 } 0158 } 0159 } 0160 0161 if( playableTrackFound && m_model->rowExists( nextRow ) ) 0162 return m_model->idAt( nextRow ); 0163 else 0164 return 0; 0165 }