1 //===========================================
2 //  Lumina-DE source code
3 //  Copyright (c) 2015, Ken Moore
4 //  Available under the 3-clause BSD license
5 //  See the LICENSE file for full details
6 //===========================================
7 #include "PlayerWidget.h"
8 #include "ui_PlayerWidget.h"
9 
10 #include <QDir>
11 #include <QUrl>
12 #include <QInputDialog>
13 #include <QFileDialog>
14 #include <LuminaXDG.h>
15 #include <QDebug>
16 #include <QDesktopWidget>
17 
PlayerWidget(QWidget * parent)18 PlayerWidget::PlayerWidget(QWidget *parent) : QWidget(parent), ui(new Ui::PlayerWidget()){
19   ui->setupUi(this); //load the designer form
20   PLAYER = new QMediaPlayer(this);
21     PLAYER->setVolume(100);
22     PLAYER->setNotifyInterval(1000); //1 second interval (just needs to be a rough estimate)
23   PLAYLIST = new QMediaPlaylist(this);
24     PLAYLIST->setPlaybackMode(QMediaPlaylist::Sequential);
25     PLAYER->setPlaylist(PLAYLIST);
26 
27   configMenu = new QMenu(this);
28     ui->tool_config->setMenu(configMenu);
29   addMenu = new QMenu(this);
30     ui->tool_add->setMenu(addMenu);
31 
32   updatinglists = false; //start off as false
33 
34   ui->combo_playlist->setContextMenuPolicy(Qt::NoContextMenu);
35 
36   LoadIcons();
37   playerStateChanged(); //update button visibility
38   currentSongChanged();
39   //Connect all the signals/slots
40   //connect(infoTimer, SIGNAL(timeout()), this, SLOT(rotateTrackInfo()) );
41   connect(PLAYER, SIGNAL(positionChanged(qint64)),this, SLOT(updateProgress(qint64)) );
42   connect(PLAYER, SIGNAL(durationChanged(qint64)), this, SLOT(updateMaxProgress(qint64)) );
43   connect(PLAYLIST, SIGNAL(mediaChanged(int, int)), this, SLOT(playlistChanged()) );
44   connect(PLAYER, SIGNAL(stateChanged(QMediaPlayer::State)), this, SLOT(playerStateChanged()) );
45   connect(PLAYLIST, SIGNAL(currentMediaChanged(const QMediaContent&)), this, SLOT(currentSongChanged()) );
46   connect(ui->combo_playlist, SIGNAL(currentIndexChanged(int)), this, SLOT(userlistSelectionChanged()) );
47   connect(ui->tool_play, SIGNAL(clicked()), this, SLOT(playClicked()) );
48   connect(ui->tool_pause, SIGNAL(clicked()), this, SLOT(pauseClicked()) );
49   connect(ui->tool_stop, SIGNAL(clicked()), this, SLOT(stopClicked()) );
50   connect(ui->tool_next, SIGNAL(clicked()), this, SLOT(nextClicked()) );
51   connect(ui->tool_prev, SIGNAL(clicked()), this, SLOT(prevClicked()) );
52 
53 }
54 
~PlayerWidget()55 PlayerWidget::~PlayerWidget(){
56   //qDebug() << "Removing PlayerWidget";
57 }
58 
LoadIcons()59 void PlayerWidget::LoadIcons(){
60   ui->tool_stop->setIcon( LXDG::findIcon("media-playback-stop","") );
61   ui->tool_play->setIcon( LXDG::findIcon("media-playback-start","") );
62   ui->tool_pause->setIcon( LXDG::findIcon("media-playback-pause","") );
63   ui->tool_next->setIcon( LXDG::findIcon("media-skip-forward","") );
64   ui->tool_prev->setIcon( LXDG::findIcon("media-skip-backward","") );
65   ui->tool_add->setIcon( LXDG::findIcon("list-add","") );
66   ui->tool_config->setIcon( LXDG::findIcon("configure","") );
67   //Now re-assemble the menus as well
68   configMenu->clear();
69   configMenu->addAction(LXDG::findIcon("media-eject",""), tr("Clear Playlist"), this, SLOT(ClearPlaylist()));
70   configMenu->addAction(LXDG::findIcon("roll",""), tr("Shuffle Playlist"), this, SLOT(ShufflePlaylist()));
71   addMenu->clear();
72   addMenu->addAction(LXDG::findIcon("document-new",""), tr("Add Files"), this, SLOT(AddFilesToPlaylist()));
73   addMenu->addAction(LXDG::findIcon("folder-new",""), tr("Add Directory"), this, SLOT(AddDirToPlaylist()));
74   addMenu->addAction(LXDG::findIcon("download",""), tr("Add URL"), this, SLOT(AddURLToPlaylist()));
75 }
76 
playClicked()77 void PlayerWidget::playClicked(){
78   PLAYER->play();
79 }
80 
pauseClicked()81 void PlayerWidget::pauseClicked(){
82   PLAYER->pause();
83 }
84 
stopClicked()85 void PlayerWidget::stopClicked(){
86   PLAYER->stop();
87 }
88 
nextClicked()89 void PlayerWidget::nextClicked(){
90   PLAYLIST->next();
91 }
92 
prevClicked()93 void PlayerWidget::prevClicked(){
94   PLAYLIST->previous();
95 }
96 
AddFilesToPlaylist()97 void PlayerWidget::AddFilesToPlaylist(){
98   //Prompt the user to select multimedia files
99   QFileDialog dlg(0, Qt::Dialog | Qt::WindowStaysOnTopHint );
100       dlg.setFileMode(QFileDialog::ExistingFiles);
101       dlg.setAcceptMode(QFileDialog::AcceptOpen);
102       dlg.setNameFilter( tr("Multimedia Files")+" ("+LXDG::findAVFileExtensions().join(" ")+")");
103       dlg.setWindowTitle(tr("Select Multimedia Files"));
104       dlg.setWindowIcon( LXDG::findIcon("file-open","") );
105       dlg.setDirectory(QDir::homePath()); //start in the home directory
106       //ensure it is centered on the current screen
107       QPoint center = QApplication::desktop()->screenGeometry(this).center();
108       dlg.move( center.x()-(dlg.width()/2), center.y()-(dlg.height()/2) );
109   dlg.show();
110   while( dlg.isVisible() ){
111     QApplication::processEvents();
112   }
113   QList<QUrl> files = dlg.selectedUrls();
114   if(files.isEmpty()  || dlg.result()!=QDialog::Accepted){ return; } //cancelled
115   //Make this use show/processEvents later
116   //QList<QUrl> files = QFileDialog::getOpenFileUrls(0, tr("Select Multimedia Files"),  QDir::homePath(), "Multimedia Files ("+LXDG::findAVFileExtensions().join(" ")+")");
117   QList<QMediaContent> urls;
118   for(int i=0; i<files.length(); i++){
119     urls << QMediaContent(files[i]);
120   }
121   PLAYLIST->addMedia(urls);
122   playlistChanged();
123 }
124 
AddDirToPlaylist()125 void PlayerWidget::AddDirToPlaylist(){
126   QFileDialog dlg(0, Qt::Dialog | Qt::WindowStaysOnTopHint );
127       dlg.setFileMode(QFileDialog::Directory);
128       dlg.setOption(QFileDialog::ShowDirsOnly, true);
129       dlg.setAcceptMode(QFileDialog::AcceptOpen);
130       dlg.setWindowTitle(tr("Select Multimedia Directory"));
131       dlg.setWindowIcon( LXDG::findIcon("folder-open","") );
132       dlg.setDirectory(QDir::homePath()); //start in the home directory
133       //ensure it is centered on the current screen
134       QPoint center = QApplication::desktop()->screenGeometry(this).center();
135       dlg.move( center.x()-(dlg.width()/2), center.y()-(dlg.height()/2) );
136   dlg.show();
137   while( dlg.isVisible() ){
138     QApplication::processEvents();
139   }
140   if(dlg.result() != QDialog::Accepted){ return; } //cancelled
141   QStringList sel = dlg.selectedFiles();
142   if(sel.isEmpty()){ return; } //cancelled
143   QString dirpath = sel.first(); //QFileDialog::getExistingDirectory(0, tr("Select a Multimedia Directory"), QDir::homePath() );
144   if(dirpath.isEmpty()){ return; } //cancelled
145   QDir dir(dirpath);
146   QFileInfoList files = dir.entryInfoList(LXDG::findAVFileExtensions(), QDir::Files | QDir::NoDotAndDotDot, QDir::Name);
147   if(files.isEmpty()){ return; } //nothing in this directory
148   QList<QMediaContent> urls;
149   for(int i=0; i<files.length(); i++){
150     urls << QMediaContent(QUrl::fromLocalFile(files[i].absoluteFilePath()) );
151   }
152   PLAYLIST->addMedia(urls);
153   playlistChanged();
154 }
155 
AddURLToPlaylist()156 void PlayerWidget::AddURLToPlaylist(){
157   QInputDialog dlg(0, Qt::Dialog | Qt::WindowStaysOnTopHint );
158       dlg.setInputMode(QInputDialog::TextInput);
159       dlg.setLabelText(tr("Enter a valid URL for a multimedia file or stream:"));
160       dlg.setTextEchoMode(QLineEdit::Normal);
161       dlg.setWindowTitle(tr("Multimedia URL"));
162       dlg.setWindowIcon( LXDG::findIcon("download","") );
163       //ensure it is centered on the current screen
164       QPoint center = QApplication::desktop()->screenGeometry(this).center();
165       dlg.move( center.x()-(dlg.width()/2), center.y()-(dlg.height()/2) );
166   dlg.show();
167   while( dlg.isVisible() ){
168     QApplication::processEvents();
169   }
170   QString url = dlg.textValue();
171   if(url.isEmpty() || dlg.result()!=QDialog::Accepted){ return; } //cancelled
172 
173   //QString url = QInputDialog::getText(0, tr("Multimedia URL"), tr("Enter a valid URL for a multimedia file or stream"), QLineEdit::Normal);
174   //if(url.isEmpty()){ return; }
175   QUrl newurl(url);
176   if(!newurl.isValid()){ return; } //invalid URL
177   PLAYLIST->addMedia(newurl);
178   playlistChanged();
179 }
180 
ClearPlaylist()181 void PlayerWidget::ClearPlaylist(){
182   PLAYER->stop();
183   PLAYLIST->clear();
184   playlistChanged();
185 }
186 
ShufflePlaylist()187 void PlayerWidget::ShufflePlaylist(){
188   PLAYLIST->shuffle();
189 }
190 
191 
userlistSelectionChanged()192 void PlayerWidget::userlistSelectionChanged(){ //front-end combobox was changed by the user
193   if(updatinglists){ return; }
194   PLAYLIST->setCurrentIndex( ui->combo_playlist->currentIndex() );
195 }
196 
playerStateChanged()197 void PlayerWidget::playerStateChanged(){
198   switch( PLAYER->state() ){
199     case QMediaPlayer::StoppedState:
200       ui->tool_stop->setVisible(false);
201       ui->tool_play->setVisible(true);
202       ui->tool_pause->setVisible(false);
203       ui->progressBar->setVisible(false);
204       break;
205     case QMediaPlayer::PausedState:
206       ui->tool_stop->setVisible(true);
207       ui->tool_play->setVisible(true);
208       ui->tool_pause->setVisible(false);
209       ui->progressBar->setVisible(true);
210       break;
211     case QMediaPlayer::PlayingState:
212       ui->tool_stop->setVisible(true);
213       ui->tool_play->setVisible(false);
214       ui->tool_pause->setVisible(true);
215       ui->progressBar->setVisible(true);
216       break;
217   }
218 
219 }
220 
playlistChanged()221 void PlayerWidget::playlistChanged(){
222   updatinglists = true;
223   ui->combo_playlist->clear();
224   for(int i=0; i<PLAYLIST->mediaCount(); i++){
225     QUrl url = PLAYLIST->media(i).canonicalUrl();
226     if(url.isLocalFile()){
227       ui->combo_playlist->addItem(LXDG::findMimeIcon(url.fileName().section(".",-1)), url.fileName() );
228     }else{
229       ui->combo_playlist->addItem(LXDG::findIcon("download",""), url.toString() );
230     }
231   }
232   if(PLAYLIST->currentIndex()<0 && PLAYLIST->mediaCount()>0){ PLAYLIST->setCurrentIndex(0); }
233   ui->combo_playlist->setCurrentIndex(PLAYLIST->currentIndex());
234 
235   updatinglists = false;
236 }
237 
currentSongChanged()238 void PlayerWidget::currentSongChanged(){
239   if(PLAYLIST->currentIndex() != ui->combo_playlist->currentIndex()){
240     updatinglists = true;
241     ui->combo_playlist->setCurrentIndex(PLAYLIST->currentIndex());
242     updatinglists = false;
243   }
244   ui->tool_next->setEnabled( PLAYLIST->nextIndex() >= 0 );
245   ui->tool_prev->setEnabled( PLAYLIST->previousIndex() >= 0);
246   ui->label_num->setText( QString::number( PLAYLIST->currentIndex()+1)+"/"+QString::number(PLAYLIST->mediaCount()) );
247   ui->progressBar->setRange(0, PLAYER->duration() );
248   ui->progressBar->setValue(0);
249 }
250 
updateProgress(qint64 val)251 void PlayerWidget::updateProgress(qint64 val){
252   //qDebug() << "Update Progress Bar:" << val;
253   ui->progressBar->setValue(val);
254 }
255 
updateMaxProgress(qint64 val)256 void PlayerWidget::updateMaxProgress(qint64 val){
257   ui->progressBar->setRange(0,val);
258 }
259 
260 
AudioPlayerPlugin(QWidget * parent,QString ID)261 AudioPlayerPlugin::AudioPlayerPlugin(QWidget *parent, QString ID) : LDPlugin(parent, ID){
262   player = new PlayerWidget(this);
263   this->setLayout( new QVBoxLayout() );
264     this->layout()->setContentsMargins(0,0,0,0);
265     this->layout()->addWidget(player);
266 
267 }
268 
~AudioPlayerPlugin()269 AudioPlayerPlugin::~AudioPlayerPlugin(){
270   //qDebug() << "Remove AudioPlayerPlugin";
271 }
272