Implemented settings dialog and refactored accordingly.
[vlc-remote] / src / playermainwindow.cpp
1   /*   VLC-REMOTE for MAEMO 5
2   *   Copyright (C) 2010 Schutz Sacha <istdasklar@gmail.com>, Dru Moore <usr@dru-id.co.uk>, Yann Nave <yannux@onbebop.net>
3   *   This program is free software; you can redistribute it and/or modify
4   *   it under the terms of the GNU General Public License version 2,
5   *   or (at your option) any later version, as published by the Free
6   *   Software Foundation
7   *
8   *   This program is distributed in the hope that it will be useful,
9   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
10   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11   *   GNU General Public License for more details
12   *
13   *   You should have received a copy of the GNU General Public
14   *   License along with this program; if not, write to the
15   *   Free Software Foundation, Inc.,
16   *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17   */
18   #include <QDebug>
19   #include <QTime>
20   #include <QtGui>
21   #include "playermainwindow.h"
22   #include "ui_playermainwindow.h"
23   #include "configdialog.h"
24   #include "aboutdialog.h"
25   #include "accountdialog.h"
26   #include "settingsdialog.h"
27   #include "appsettings.h"
28 #if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5)
29 #include <QMaemo5InformationBox>
30 #endif
31 #include <QMessageBox>
32
33   PlayerMainWindow::PlayerMainWindow(QWidget *parent) :
34           QMainWindow(parent),
35           ui(new Ui::PlayerMainWindow)
36   {
37       ui->setupUi(this);
38       setWindowTitle("Vlc remote");
39
40       mIsFirstStatusCall = true;
41
42       mTimer = new QTimer(this);
43       mNetManager = new QNetworkAccessManager(this);
44       mPlayListMainWindow = new PlayListMainWindow;
45       mBrowserMainWindow = new BrowseMainWindow;
46       mFavouritesMainWindow = new FavouritesMainWindow;
47
48       mVolume = 100;
49       mMuted = false;
50
51       mIsLandscape = true;
52
53       ui->playlistButton->setIcon(QIcon::fromTheme("notes_bullets"));
54       ui->browseButton->setIcon(QIcon::fromTheme("filemanager_media_folder"));
55
56       ui->previousButton->setIcon(QIcon::fromTheme("pdf_viewer_first_page"));
57       ui->nextButton->setIcon(QIcon::fromTheme("pdf_viewer_last_page"));
58       ui->playpauseButton->setIcon(QIcon::fromTheme("camera_playback"));
59       ui->stopButton->setIcon(QIcon::fromTheme("camera_video_stop"));
60       ui->fullscreenButton->setIcon(QIcon::fromTheme("general_fullsize"));
61       ui->volDown->setIcon(QIcon::fromTheme("statusarea_volumelevel1"));
62       ui->volUp->setIcon(QIcon::fromTheme("statusarea_volumelevel4"));
63       ui->volMute->setIcon(QIcon::fromTheme("statusarea_volume_mute"));
64
65       ui->labelArtPortrait->setVisible(false);
66       ui->labelArtLandscape->setVisible(false);
67
68       ui->labelTitle->setTextFormat(Qt::RichText);
69       ui->labelArtist->setTextFormat(Qt::RichText);
70       ui->labelAlbum->setTextFormat(Qt::RichText);
71
72
73   #if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5)
74
75       mPlayListMainWindow->setParent(this);
76       mPlayListMainWindow->setAttribute(Qt::WA_Maemo5StackedWindow, true);
77       setAttribute(Qt::WA_Maemo5StackedWindow, true);
78       mPlayListMainWindow->setWindowFlags(mPlayListMainWindow->windowFlags() | Qt::Window);
79
80       mBrowserMainWindow->setParent(this);
81       mBrowserMainWindow->setAttribute(Qt::WA_Maemo5StackedWindow, true);
82       setAttribute(Qt::WA_Maemo5StackedWindow, true);
83       mBrowserMainWindow->setWindowFlags(mBrowserMainWindow->windowFlags() | Qt::Window);
84
85       mFavouritesMainWindow->setParent(this);
86       mFavouritesMainWindow->setAttribute(Qt::WA_Maemo5StackedWindow, true);
87       setAttribute(Qt::WA_Maemo5StackedWindow, true);
88       mFavouritesMainWindow->setWindowFlags(mFavouritesMainWindow->windowFlags() | Qt::Window);
89
90       connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(orientationChanged()));
91
92   #endif
93
94       connect(mTimer,SIGNAL(timeout()),this,SLOT(askStatus()));
95       connect(ui->actionSettings,SIGNAL(triggered()),this,SLOT(showSettings()));
96       connect(ui->actionConfiguration,SIGNAL(triggered()),this,SLOT(showConfig()));
97       connect(ui->actionAbout,SIGNAL(triggered()),this,SLOT(showAbout()));
98       connect(ui->actionFavourites,SIGNAL(triggered()),this,SLOT(showFavourites()));
99       //connect(ui->actionPortrait,SIGNAL(triggered()),this,SLOT(setPortrait()));
100       //connect(ui->actionLandscape,SIGNAL(triggered()),this,SLOT(setLandscape()));
101       //connect(ui->actionAutoRotate,SIGNAL(triggered()),this,SLOT(setAutoRotate()));
102       connect(ui->playlistButton,SIGNAL(clicked()),mPlayListMainWindow,SLOT(show()));
103       connect(ui->playlistButton,SIGNAL(clicked()),mPlayListMainWindow,SLOT(showPlayList()));
104       connect(ui->browseButton,SIGNAL(clicked()),mBrowserMainWindow,SLOT(show()));
105       connect(ui->browseButton,SIGNAL(clicked()),mBrowserMainWindow,SLOT(showCurrentDirectory()));
106
107       connect(ui->playpauseButton,SIGNAL(clicked()),this,SLOT(playpause()));
108       connect(ui->stopButton,SIGNAL(clicked()),this,SLOT(stop()));
109       connect(ui->previousButton,SIGNAL(clicked()),this,SLOT(previous()));
110       connect(ui->nextButton,SIGNAL(clicked()),this,SLOT(next()));
111       connect(ui->fullscreenButton,SIGNAL(clicked()),this,SLOT(fullscreen()));
112       connect(ui->volUp,SIGNAL(clicked()),this,SLOT(volUp()));
113       connect(ui->volDown,SIGNAL(clicked()),this,SLOT(volDown()));
114       connect(ui->volMute,SIGNAL(clicked()),this,SLOT(volMute()));
115       connect(ui->slider,SIGNAL(sliderMoved(int)),this,SLOT(slide(int)));
116
117       connect(mPlayListMainWindow, SIGNAL(idUpdated(int,bool,QString)), this, SLOT(playlistIdUpdated(int, bool, QString)));
118       connect(mBrowserMainWindow, SIGNAL(showFavouritesWindow()), this, SLOT(showFavourites()));
119
120       connect(mFavouritesMainWindow, SIGNAL(browseDirectory(QString)), mFavouritesMainWindow, SLOT(close()));
121       connect(mFavouritesMainWindow, SIGNAL(browseDirectory(QString)), mBrowserMainWindow, SLOT(browseDirectory(QString)));
122       connect(mFavouritesMainWindow, SIGNAL(closeSignal()), mBrowserMainWindow, SLOT(show()));
123
124
125       // check if last used connection is still valid or showConfig
126
127       // check for network
128       if (AppSettings::isConnected()) {
129           QSettings settings;
130           QString last_ip = AppSettings::getCurrentIp(); // AccountDialog::currentIp();
131           if (!last_ip.isNull() && !last_ip.isEmpty()) {
132               QTcpSocket * socket = new QTcpSocket;
133               if(last_ip.contains(":"))
134               {
135                   QStringList hostSplit = last_ip.split(":");
136                   QString ip   = hostSplit.at(0);
137                   QString port = hostSplit.at(1);
138                   socket->connectToHost(ip,port.toInt());
139               }
140               else {
141                   socket->connectToHost(last_ip,8080);
142               }
143               if (!socket->waitForConnected(AppSettings::getConnectionTimeout())) {
144                      showConfig();
145                  }
146               else {
147                   mIp= last_ip;
148
149                  mPlayListMainWindow->init();
150                  mBrowserMainWindow->init();
151                  mTimer->start(AppSettings::getStatusPollTimeout());
152                  askStatus();
153               }
154               delete socket;
155           }
156           else {
157             showConfig();
158           }
159       }
160       else {
161 #if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5)
162         QMaemo5InformationBox::information(this, tr("Network unavailable!"), QMaemo5InformationBox::DefaultTimeout);
163 #endif
164           showConfig();
165       }
166   }
167   
168
169   PlayerMainWindow::~PlayerMainWindow()
170   {
171       delete ui;
172   }
173
174   void PlayerMainWindow::changeEvent(QEvent *e)
175   {
176       QMainWindow::changeEvent(e);
177       switch (e->type()) {
178       case QEvent::LanguageChange:
179           ui->retranslateUi(this);
180           break;
181       default:
182           break;
183       }
184   }
185
186   void PlayerMainWindow::showFavourites() {
187       mFavouritesMainWindow->show();
188       mFavouritesMainWindow->init();
189   }
190
191   void PlayerMainWindow::updateFromSettings()
192   {
193     #if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5)
194     switch (AppSettings::getOrientation()) {
195       case LANDSCAPE:
196           this->setAttribute(Qt::WA_Maemo5LandscapeOrientation, true);
197           break;
198       case PORTRAIT:
199           this->setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
200           break;
201       case AUTO_ROTATE:
202           this->setAttribute(Qt::WA_Maemo5AutoOrientation, true);
203           break;
204     }
205     #endif
206     if (AppSettings::getShowAlbumArt()) {
207         this->mIsFirstStatusCall = true;
208     }
209     mTimer->start(AppSettings::getStatusPollTimeout());
210   }
211
212   void PlayerMainWindow::setPortrait()
213   {
214     #if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5)
215       AppSettings::setOrientation(PORTRAIT);
216     this->setAttribute(Qt::WA_Maemo5PortraitOrientation, true);
217     #endif
218   }
219
220   void PlayerMainWindow::setLandscape()
221   {
222     #if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5)
223       AppSettings::setOrientation(LANDSCAPE);
224     this->setAttribute(Qt::WA_Maemo5LandscapeOrientation, true);
225     #endif
226   }
227
228   void PlayerMainWindow::setAutoRotate()
229   {
230     #if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5)
231       AppSettings::setOrientation(AUTO_ROTATE);
232     this->setAttribute(Qt::WA_Maemo5AutoOrientation, true);
233     #endif
234   }
235
236   void PlayerMainWindow::orientationChanged() {
237       QRect screenGeometry = QApplication::desktop()->screenGeometry();
238       mIsLandscape = (screenGeometry.width() > screenGeometry.height());
239       if (mHasImage) {
240           if (mIsLandscape) {
241               ui->labelArtPortrait->setVisible(false);
242               ui->labelArtLandscape->setVisible(true);
243           }
244           else {
245               ui->labelArtLandscape->setVisible(false);
246               ui->labelArtPortrait->setVisible(true);
247           }
248       }
249       else {
250           ui->labelArtLandscape->setVisible(false);
251           ui->labelArtPortrait->setVisible(false);
252       }
253   }
254
255   void PlayerMainWindow::playpause()
256   {
257       // NB. There is no guarentee that our current state is the real current state.
258       // This is due to the polling frequency and possibility of user interaction directly on the server.
259       // Still this is probably better than nothing and our next real poll will set us straight again.
260       if (PAUSED == mCurrentStatus.state) {
261         mCurrentStatus.state = PLAYING;
262         pause();
263         updateUiWithCurrentStatus();
264       }
265       else if (PLAYING == mCurrentStatus.state) {
266         mCurrentStatus.state = PAUSED;
267         pause();
268         updateUiWithCurrentStatus();
269       }
270       else {
271         // could be STOP or UNKNOWN, either way there is no guarentee we will enter a playing state next.
272         // So don't update the current state or UI
273         // Ideally we would try to find a way to check the current state again but this could lead to an infinite loop!
274         play();
275       }
276   }
277   void PlayerMainWindow::play()
278   {
279       mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=pl_play")));
280   }
281   void PlayerMainWindow::stop()
282   {
283       mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=pl_stop")));
284   }
285   void PlayerMainWindow::pause()
286   {
287       mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=pl_pause")));
288   }
289   void PlayerMainWindow::previous()
290   {
291       mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=pl_previous")));
292   }
293   void PlayerMainWindow::next()
294   {
295       mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=pl_next")));
296   }
297   void PlayerMainWindow::fullscreen()
298   {
299       mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=fullscreen")));
300   }
301   void PlayerMainWindow::volUp()
302   {
303       QUrl url = QUrl("http://"+mIp+"/requests/status.xml?command=volume");
304       url.addEncodedQueryItem(QByteArray("val"), QByteArray("%2B10"));
305       mNetManager->get(QNetworkRequest(url));
306   }
307   void PlayerMainWindow::volDown()
308   {
309       mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=volume&val=-10")));
310   }
311   void PlayerMainWindow::volMute()
312   {
313       this->mMuted = !this->mMuted;
314       if (this->mMuted) {
315           mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=volume&val=0")));
316       }
317       else {
318           mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=volume&val="+QString::number(this->mVolume))));
319       }
320   }
321   void PlayerMainWindow::slide(int value)
322   {
323       mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=seek&val="+QString::number(value)+"%25")));
324   }
325
326   void PlayerMainWindow::showSettings()
327   {
328     SettingsDialog * dialog = new SettingsDialog(this);
329     connect(dialog, SIGNAL(closeSignal()), this, SLOT(updateFromSettings()));
330     dialog->exec();
331   }
332   void PlayerMainWindow::showConfig()
333   {
334       mTimer->stop();
335       // check for network
336       if (AppSettings::isConnected()) {
337           AccountDialog * dialog = new AccountDialog(this);
338           dialog->exec();
339
340           mIp= AppSettings::getCurrentIp(); //AccountDialog::currentIp();
341
342           mPlayListMainWindow->init();
343           mBrowserMainWindow->init();
344           mTimer->start(AppSettings::getStatusPollTimeout());
345           askStatus();
346       }
347       else {
348 #if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5)
349         QMaemo5InformationBox::information(this, tr("Network unavailable!"), QMaemo5InformationBox::DefaultTimeout);
350 #endif
351         QTimer::singleShot(AppSettings::getRetryNetworkTimeout(), this, SLOT(showConfig()));
352       }
353   }
354   void PlayerMainWindow::showAbout()
355   {
356
357       AboutDialog * dialog = new AboutDialog;
358       dialog->exec();
359
360   }
361
362   void PlayerMainWindow::askStatus()
363   {
364       //qDebug() << "Status requested. at:" << QTime::currentTime().toString("hh::mm:ss");
365       if (AppSettings::isConnected()) {
366           QNetworkReply * reply =  mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml")));
367           connect(reply,SIGNAL(readyRead()),this,SLOT(parseXmlStatus()));
368           connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(error(QNetworkReply::NetworkError)));
369       }
370       else {
371         showConfig(); // this will handle stopping and restarting the timer.
372       }
373   }
374
375   void PlayerMainWindow::parseXmlStatus()
376   {
377       QNetworkReply * reply = qobject_cast<QNetworkReply*>(sender());
378       QDomDocument doc;
379       doc.setContent(reply->readAll());
380       delete reply;
381       QDomElement docElem = doc.documentElement();
382       VlcStatusState oldState = mCurrentStatus.state;
383       // Get the raw values
384       int volume = docElem.namedItem("volume").toElement().text().toInt();
385       int length = docElem.namedItem("length").toElement().text().toInt();
386       int time = docElem.namedItem("time").toElement().text().toInt();
387       int position = docElem.namedItem("position").toElement().text().toInt();
388       int random = docElem.namedItem("random").toElement().text().toInt();
389       int loop = docElem.namedItem("loop").toElement().text().toInt();
390       int repeat = docElem.namedItem("repeat").toElement().text().toInt();
391       QString state = docElem.namedItem("state").toElement().text();
392       QDomNode infoNode =  docElem.namedItem("information");
393       QDomNode metaInfoNode =  infoNode.namedItem("meta-information");
394       QString title = metaInfoNode.namedItem("title").toElement().text().replace("\\\\", "\\");
395       // if it's a file style title fix it up
396       if (40 < title.length()) {
397           if (0 < title.lastIndexOf("\\")) {
398               title = title.right(title.length() - (title.lastIndexOf("\\") + 1));
399           }
400           else if (0 < title.lastIndexOf("/")) {
401               title = title.right(title.length() - (title.lastIndexOf("/") + 1));
402           }
403       }
404       QString artist = metaInfoNode.namedItem("artist").toElement().text();
405       QString album = metaInfoNode.namedItem("album").toElement().text();
406       QString now_playing = metaInfoNode.namedItem("now_playing").toElement().text();
407       QString art_url = metaInfoNode.namedItem("art_url").toElement().text();
408       // Populate the current status structure
409       // now would be a good time to work out if we are a new track / file or not.
410       // key if we are going to look for album art later
411       // for now we check length and title this will require further examination later
412       if (!state.isNull() && !state.isEmpty()) {
413           if (0 == QString::compare("playing", state, Qt::CaseInsensitive)) {
414             mCurrentStatus.state = PLAYING;
415           }
416           else if (0 == QString::compare("paused", state, Qt::CaseInsensitive)) {
417             mCurrentStatus.state = PAUSED;
418           }
419           else if (0 == QString::compare("stop", state, Qt::CaseInsensitive)) {
420             mCurrentStatus.state = STOP;
421           }
422           else {
423             mCurrentStatus.state = UNKNOWN;
424             mIsFirstStatusCall = true;
425           }
426       }
427       else {
428           mCurrentStatus.state = UNKNOWN;
429           mIsFirstStatusCall = true;
430       }
431       mCurrentStatus.newtrack = true;
432       if (mIsFirstStatusCall) {
433           mIsFirstStatusCall = false;
434           mCurrentStatus.newtrack = true; // unneeded but self-documenting
435       }
436       else if (STOP == oldState && STOP != mCurrentStatus.state) {
437           mCurrentStatus.newtrack = true; // unneeded but self-documenting
438       }
439       else {
440           if ( (0 == mCurrentStatus.length || STOP == mCurrentStatus.state) // stopped or null
441                   || // same track as current playing
442                (mCurrentStatus.length == length && !mCurrentStatus.title.isNull() && !title.isNull() && 0 == QString::compare(mCurrentStatus.title, title)) ){
443             mCurrentStatus.newtrack = false;
444           }
445       }
446       mCurrentStatus.volume = volume;
447       mCurrentStatus.length = length;
448       mCurrentStatus.time = time;
449       mCurrentStatus.position = position;
450       mCurrentStatus.random = (1 == random);
451       mCurrentStatus.loop = (1 == loop);
452       mCurrentStatus.repeat = (1 == repeat);
453       mCurrentStatus.title = title;
454       mCurrentStatus.artist = artist;
455       mCurrentStatus.album = album;
456       mCurrentStatus.nowplaying = now_playing;
457       mCurrentStatus.hasart = (!art_url.isNull() && !art_url.isEmpty());
458       // What's our mute status?
459       if (0 < mCurrentStatus.volume) {
460           this->mVolume = mCurrentStatus.volume;
461           this->mMuted = false;
462       }
463       else {
464           this->mMuted = true;
465       }
466       // Update the UI
467       updateUiWithCurrentStatus();
468
469   }
470
471   void PlayerMainWindow::updateUiWithCurrentStatus() {
472       // position
473       QTime timePosition(0,0,0) ;
474       timePosition =  timePosition.addSecs(mCurrentStatus.time);
475
476       ui->timeLabel->setText(timePosition.toString("h:mm:ss"));
477
478       // duration
479       if (0 < mCurrentStatus.length) {
480           QTime timeDuration(0,0,0) ;
481           timeDuration =  timeDuration.addSecs(mCurrentStatus.length);
482
483           ui->durationLabel->setText(timeDuration.toString("h:mm:ss"));
484       }
485       else {
486           ui->durationLabel->setText("0:00:00");
487       }
488
489
490       if (mCurrentStatus.position >= 0 && mCurrentStatus.position <= 100) {
491           ui->slider->blockSignals(true);
492           ui->slider->setValue(mCurrentStatus.position);
493           ui->slider->blockSignals(false);
494       }
495
496       ui->labelTitle->setText(mCurrentStatus.title);
497       ui->labelArtist->setText(mCurrentStatus.artist);
498       ui->labelAlbum->setText(mCurrentStatus.album);
499
500       if (PLAYING == mCurrentStatus.state) {
501           ui->playpauseButton->setIcon(QIcon::fromTheme("camera_video_pause"));
502       }
503       else {
504           ui->playpauseButton->setIcon(QIcon::fromTheme("camera_playback"));
505       }
506
507       if (STOP == mCurrentStatus.state || !AppSettings::getShowAlbumArt()) {
508           ui->labelArtPortrait->setVisible(false);
509           ui->labelArtLandscape->setVisible(false);
510       }
511
512       if (mCurrentStatus.newtrack && STOP != mCurrentStatus.state) {
513           // potential actions:
514           //   rebuild display layout
515           //   retrieve album art
516           if (AppSettings::getShowAlbumArt()) {
517               mHasImage = false;
518               QTimer::singleShot(AppSettings::getRetrieveArtTimeout(), mPlayListMainWindow, SLOT(requestPlayList()));
519           }
520       }
521       // Update the buttons on the playlist window
522       if (NULL != this->mPlayListMainWindow) {
523         this->mPlayListMainWindow->updateUiWithCurrentStatus(& mCurrentStatus);
524       }
525
526   }
527   void PlayerMainWindow::playlistIdUpdated(int id, bool hasart, QString extension) {
528       Q_UNUSED(extension);
529       if (hasart) {
530           getCoverArt(id);
531       }
532       else {
533           ui->labelArtLandscape->setVisible(false);
534           ui->labelArtPortrait->setVisible(false);
535           // could use a default graphic from extension here!
536           // setCoverArtFromPixmap();
537       }
538   }
539   void PlayerMainWindow::error(QNetworkReply::NetworkError code) {
540       qDebug() << "Error Code: " << code;
541   }
542   void PlayerMainWindow::readReady() {
543     QNetworkReply * reply = qobject_cast<QNetworkReply*>(sender());
544     // append to buffer
545     mResponse += reply->readAll();
546   }
547   void PlayerMainWindow::finished(QNetworkReply * reply) {
548     // now we can call setCoverArt to process the full buffers
549     this->setCoverArt(mResponse);
550     // only interested in finished signals
551     disconnect(mNetManager,SIGNAL(finished(QNetworkReply *)),this,SLOT(finished(QNetworkReply *)));
552     delete reply;
553   }
554   void PlayerMainWindow::getCoverArt(int id) {
555       qDebug() << "getCoverArt id=!" << id;
556     mResponse.clear();
557     QNetworkReply * reply =  mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/art?id=" + QString::number(id))));
558     connect(reply,SIGNAL(readyRead()),this,SLOT(readReady()));
559     connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(error(QNetworkReply::NetworkError)));
560     connect(mNetManager,SIGNAL(finished(QNetworkReply *)),this,SLOT(finished(QNetworkReply *)));
561
562   }
563   void PlayerMainWindow::setCoverArt(const QByteArray data) {
564     QPixmap* image = new QPixmap();
565     if (image->loadFromData(data)) {
566         mHasImage = true;
567         ui->labelArtLandscape->setPixmap(image->scaledToHeight(120, Qt::SmoothTransformation));
568         ui->labelArtPortrait->setPixmap(image->scaledToHeight(310, Qt::SmoothTransformation));
569         if (mIsLandscape) {
570             ui->labelArtPortrait->setVisible(false);
571             ui->labelArtLandscape->setVisible(true);
572         }
573         else {
574             ui->labelArtLandscape->setVisible(false);
575             ui->labelArtPortrait->setVisible(true);
576         }
577     }
578     else {
579         qDebug() << "image load failed!";
580         qDebug() << "data.length" << data.length();
581         ui->labelArtPortrait->setVisible(false);
582         ui->labelArtLandscape->setVisible(false);
583     }
584     delete image;
585   }
586   void PlayerMainWindow::setCoverArtFromPixmap(QPixmap image) {
587     mHasImage = true;
588     ui->labelArtLandscape->setPixmap(image.scaledToHeight(120, Qt::SmoothTransformation));
589     ui->labelArtPortrait->setPixmap(image.scaledToHeight(320, Qt::SmoothTransformation));
590     if (mIsLandscape) {
591         ui->labelArtPortrait->setVisible(false);
592         ui->labelArtLandscape->setVisible(true);
593     }
594     else {
595         ui->labelArtLandscape->setVisible(false);
596         ui->labelArtPortrait->setVisible(true);
597     }
598   }
599   void PlayerMainWindow::closeEvent(QCloseEvent * event) {
600       if (!AppSettings::getAlertOnClose() || PLAYING != mCurrentStatus.state) {
601           event->accept();
602       }
603       else { // handle alert
604           if (QMessageBox::Yes == QMessageBox::question(this
605                                                        , tr("Really quit?")
606                                                        , tr("You currently have media playing on your remote machine. Are you sure you wish to quit vlc-remote?")
607                                                        , QMessageBox::Yes | QMessageBox::No
608                                                        , QMessageBox::No)) {
609             event->accept();
610           }
611           else {
612             event->ignore();
613           }
614       }
615   }
616