File indexing completed on 2024-05-05 05:40:23
0001 /*************************************************************************** 0002 * Copyright (C) 2021 by Renaud Guezennec * 0003 * http://www.rolisteam.org/contact * 0004 * * 0005 * This software is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0019 ***************************************************************************/ 0020 #include "controller/audioplayercontroller.h" 0021 0022 #include "preferences/preferencesmanager.h" 0023 #include "worker/iohelper.h" 0024 #include "worker/modelhelper.h" 0025 0026 #include <chrono> 0027 #include <random> 0028 0029 int randomSong(int current, int count) 0030 { 0031 static auto seed= std::chrono::high_resolution_clock::now().time_since_epoch().count(); 0032 static std::mt19937 rng= std::mt19937(static_cast<unsigned long long>(seed)); 0033 std::uniform_int_distribution<qint64> dist(0, count - 1); 0034 0035 if(count < 0) 0036 return -1; 0037 if(count < 1) 0038 return 0; 0039 if(count < 2) 0040 return current == 1 ? 0 : 1; 0041 0042 int res= current; 0043 while(res == current) 0044 { 0045 res= dist(rng); 0046 } 0047 return res; 0048 } 0049 0050 AudioPlayerController::AudioPlayerController(int id, const QString& key, PreferencesManager* pref, QObject* parent) 0051 : QObject(parent), m_id(id), m_model(new MusicModel), m_pref(pref), m_prefkey(key) 0052 { 0053 m_player.setAudioOutput(&m_audioOutput); 0054 0055 // m_player.setAudioRole(QAudio::MusicRole); 0056 connect(&m_player, &QMediaPlayer::errorOccurred, this, 0057 [this](QMediaPlayer::Error, const QString& errorStr) { emit errorChanged(errorStr); }); 0058 0059 connect(&m_player, &QMediaPlayer::playbackStateChanged, this, [this]() { emit stateChanged(state()); }); 0060 connect(&m_audioOutput, &QAudioOutput::volumeChanged, this, [this]() { emit volumeChanged(volume()); }); 0061 connect(&m_audioOutput, &QAudioOutput::mutedChanged, this, &AudioPlayerController::mutedChanged); 0062 connect(&m_player, &QMediaPlayer::durationChanged, this, &AudioPlayerController::durationChanged); 0063 //connect(&m_player, &QMediaPlayer::positionChanged, this, &AudioPlayerController::timeChanged); 0064 0065 connect(&m_player, &QMediaPlayer::mediaStatusChanged, this, 0066 [this](QMediaPlayer::MediaStatus status) 0067 { 0068 switch(status) 0069 { 0070 case QMediaPlayer::EndOfMedia: 0071 next(); 0072 break; 0073 default: 0074 break; 0075 } 0076 }); 0077 } 0078 0079 AudioPlayerController::~AudioPlayerController()= default; 0080 0081 int AudioPlayerController::id() const 0082 { 0083 return m_id; 0084 } 0085 0086 AudioPlayerController::PlayingMode AudioPlayerController::mode() const 0087 { 0088 return m_mode; 0089 } 0090 0091 MusicModel* AudioPlayerController::model() const 0092 { 0093 return m_model.get(); 0094 } 0095 0096 QString AudioPlayerController::error() const 0097 { 0098 return m_player.errorString(); 0099 } 0100 0101 bool AudioPlayerController::visible() const 0102 { 0103 return m_visible; 0104 } 0105 0106 bool AudioPlayerController::muted() const 0107 { 0108 return m_audioOutput.isMuted(); 0109 } 0110 0111 quint64 AudioPlayerController::time() const 0112 { 0113 return m_player.position(); 0114 } 0115 0116 AudioPlayerController::State AudioPlayerController::state() const 0117 { 0118 AudioPlayerController::State state= AudioPlayerController::StoppedState; 0119 switch(m_player.playbackState()) 0120 { 0121 case QMediaPlayer::StoppedState: 0122 state= AudioPlayerController::StoppedState; 0123 break; 0124 case QMediaPlayer::PausedState: 0125 state= AudioPlayerController::PausedState; 0126 break; 0127 case QMediaPlayer::PlayingState: 0128 state= AudioPlayerController::PlayingState; 0129 break; 0130 } 0131 0132 if(m_player.error() != QMediaPlayer::NoError) 0133 state= AudioPlayerController::ErrorState; 0134 0135 return state; 0136 } 0137 0138 QString AudioPlayerController::text() const 0139 { 0140 return m_text; 0141 } 0142 0143 uint AudioPlayerController::volume() const 0144 { 0145 qreal linearVolume 0146 = QAudio::convertVolume(m_audioOutput.volume(), QAudio::LinearVolumeScale, QAudio::LogarithmicVolumeScale); 0147 0148 return qRound(linearVolume * 100); 0149 } 0150 0151 bool AudioPlayerController::localIsGm() const 0152 { 0153 return m_localIsGM; 0154 } 0155 0156 void AudioPlayerController::setMedia(const QModelIndex& index) 0157 { 0158 m_text= m_model->data(index, MusicModel::TITLE).toString(); 0159 m_player.setSource(m_model->data(index, MusicModel::URL).toUrl()); 0160 m_model->setCurrentSong(index); 0161 emit textChanged(); 0162 } 0163 0164 void AudioPlayerController::play() 0165 { 0166 m_player.play(); 0167 auto url= m_player.source(); 0168 emit startPlayingSong(url.isLocalFile() ? url.fileName() : url.toString(), m_player.position()); 0169 } 0170 0171 void AudioPlayerController::stop() 0172 { 0173 m_player.stop(); 0174 } 0175 0176 void AudioPlayerController::pause() 0177 { 0178 m_player.pause(); 0179 } 0180 0181 void AudioPlayerController::next() 0182 { 0183 auto p= m_model->indexOfCurrent(); 0184 auto start= true; 0185 switch(m_mode) 0186 { 0187 case LOOP: 0188 play(); 0189 break; 0190 case UNIQUE: 0191 start= false; 0192 stop(); 0193 break; 0194 case NEXT: 0195 setMedia(m_model->index(p + 1, 0)); 0196 play(); 0197 break; 0198 case SHUFFLE: 0199 setMedia(m_model->index(randomSong(p, m_model->rowCount()), 0)); 0200 play(); 0201 break; 0202 } 0203 if(start) 0204 { 0205 auto url= m_player.source(); 0206 emit startPlayingSong(url.isLocalFile() ? url.fileName() : url.toString(), m_player.position()); 0207 } 0208 } 0209 0210 void AudioPlayerController::setPlayingMode(PlayingMode mode) 0211 { 0212 if(m_mode == mode) 0213 return; 0214 m_mode= mode; 0215 emit modeChanged(); 0216 } 0217 0218 void AudioPlayerController::loadPlayList(const QString& path) 0219 { 0220 auto urls= IOHelper::readM3uPlayList(path); 0221 m_model->addSong(urls); 0222 } 0223 0224 void AudioPlayerController::setVolume(uint volume) 0225 { 0226 qreal linearVolume 0227 = QAudio::convertVolume(volume / qreal(100.0), QAudio::LogarithmicVolumeScale, QAudio::LinearVolumeScale); 0228 0229 m_audioOutput.setVolume(linearVolume); 0230 } 0231 0232 void AudioPlayerController::exportList(const QString& path) 0233 { 0234 IOHelper::writePlaylist(path, m_model->urls()); 0235 } 0236 0237 void AudioPlayerController::mute() 0238 { 0239 m_audioOutput.setMuted(!m_audioOutput.isMuted()); 0240 } 0241 0242 void AudioPlayerController::clear() 0243 { 0244 m_model->removeAll(); 0245 } 0246 0247 void AudioPlayerController::removeSong(const QModelIndexList& index) 0248 { 0249 m_model->removeSong(index); 0250 } 0251 0252 void AudioPlayerController::addSong(const QList<QUrl>& path) 0253 { 0254 m_model->addSong(path); 0255 } 0256 0257 void AudioPlayerController::setLocalIsGm(bool b) 0258 { 0259 if(b == m_localIsGM) 0260 return; 0261 m_localIsGM= b; 0262 emit localIsGmChanged(); 0263 } 0264 0265 void AudioPlayerController::setVisible(bool b) 0266 { 0267 if(m_visible == b) 0268 return; 0269 m_visible= b; 0270 emit visibleChanged(b); 0271 } 0272 0273 void AudioPlayerController::setTime(quint64 time) 0274 { 0275 m_player.setPosition(static_cast<qint64>(time)); 0276 emit timeChanged(time); 0277 } 0278 0279 void AudioPlayerController::addMusicModel() 0280 { 0281 ModelHelper::fetchMusicModelWithTableTop(m_model.get()); 0282 } 0283 0284 QStringList AudioPlayerController::directoriesList() const 0285 { 0286 if(!m_pref) 0287 return {}; 0288 return m_pref->value(m_prefkey, {}).toStringList(); 0289 } 0290 0291 void AudioPlayerController::nwNewSong(const QString& name, qint64 time) 0292 { 0293 if(localIsGm()) 0294 return; 0295 QStringList list= directoriesList(); 0296 0297 auto url= IOHelper::findSong(name, list); 0298 0299 m_text= url.fileName(); 0300 m_player.setSource(url); 0301 m_player.setPosition(time); 0302 m_player.play(); 0303 emit textChanged(); 0304 }