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
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
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.
20 #include "playermainwindow.h"
21 #include "ui_playermainwindow.h"
22 #include "configdialog.h"
23 #include "aboutdialog.h"
24 #include "accountdialog.h"
25 //#include "vlcstatus.h"
27 PlayerMainWindow::PlayerMainWindow(QWidget *parent) :
29 ui(new Ui::PlayerMainWindow)
32 setWindowTitle("Vlc remote");
36 mTimer = new QTimer(this);
37 mNetManager = new QNetworkAccessManager(this);
38 mPlayListMainWindow = new PlayListMainWindow;
39 mBrowserMainWindow = new BrowseMainWindow;
44 ui->playlistButton->setIcon(QIcon::fromTheme("notes_bullets"));
45 ui->browseButton->setIcon(QIcon::fromTheme("filemanager_media_folder"));
47 ui->previousButton->setIcon(QIcon::fromTheme("pdf_viewer_first_page"));
48 ui->nextButton->setIcon(QIcon::fromTheme("pdf_viewer_last_page"));
49 ui->playpauseButton->setIcon(QIcon::fromTheme("camera_playback"));
50 ui->stopButton->setIcon(QIcon::fromTheme("camera_video_stop"));
51 //ui->pauseButton->setIcon(QIcon::fromTheme("camera_video_pause"));
52 ui->fullscreenButton->setIcon(QIcon::fromTheme("general_fullsize"));
53 ui->volDown->setIcon(QIcon::fromTheme("statusarea_volumelevel1"));
54 ui->volUp->setIcon(QIcon::fromTheme("statusarea_volumelevel4"));
55 ui->volMute->setIcon(QIcon::fromTheme("statusarea_volume_mute"));
58 #if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5)
59 mPlayListMainWindow->setParent(this);
60 mPlayListMainWindow->setAttribute(Qt::WA_Maemo5StackedWindow);
61 mPlayListMainWindow->setAttribute(Qt::WA_Maemo5LandscapeOrientation,true);
62 mPlayListMainWindow->setAttribute(Qt::WA_Maemo5LandscapeOrientation,true);
63 setAttribute(Qt::WA_Maemo5StackedWindow);
64 mPlayListMainWindow->setWindowFlags(mPlayListMainWindow->windowFlags() | Qt::Window);
66 mBrowserMainWindow->setParent(this);
67 mBrowserMainWindow->setAttribute(Qt::WA_Maemo5StackedWindow);
68 mBrowserMainWindow->setAttribute(Qt::WA_Maemo5LandscapeOrientation,true);
69 mBrowserMainWindow->setAttribute(Qt::WA_Maemo5LandscapeOrientation,true);
70 setAttribute(Qt::WA_Maemo5StackedWindow);
71 mBrowserMainWindow->setWindowFlags(mBrowserMainWindow->windowFlags() | Qt::Window);
75 connect(mTimer,SIGNAL(timeout()),this,SLOT(askStatus()));
76 connect(ui->actionConfiguration,SIGNAL(triggered()),this,SLOT(showConfig()));
77 connect(ui->actionAbout,SIGNAL(triggered()),this,SLOT(showAbout()));
78 connect(ui->playlistButton,SIGNAL(clicked()),mPlayListMainWindow,SLOT(show()));
79 connect(ui->playlistButton,SIGNAL(clicked()),mPlayListMainWindow,SLOT(showPlayList()));
80 connect(ui->browseButton,SIGNAL(clicked()),mBrowserMainWindow,SLOT(show()));
81 connect(ui->browseButton,SIGNAL(clicked()),mBrowserMainWindow,SLOT(showCurrentDirectory()));
83 connect(ui->playpauseButton,SIGNAL(clicked()),this,SLOT(playpause()));
84 connect(ui->stopButton,SIGNAL(clicked()),this,SLOT(stop()));
85 //connect(ui->pauseButton,SIGNAL(clicked()),this,SLOT(playpause()));
86 connect(ui->previousButton,SIGNAL(clicked()),this,SLOT(previous()));
87 connect(ui->nextButton,SIGNAL(clicked()),this,SLOT(next()));
88 connect(ui->fullscreenButton,SIGNAL(clicked()),this,SLOT(fullscreen()));
89 connect(ui->volUp,SIGNAL(clicked()),this,SLOT(volUp()));
90 connect(ui->volDown,SIGNAL(clicked()),this,SLOT(volDown()));
91 connect(ui->volMute,SIGNAL(clicked()),this,SLOT(volMute()));
92 connect(ui->slider,SIGNAL(sliderMoved(int)),this,SLOT(slide(int)));
100 PlayerMainWindow::~PlayerMainWindow()
105 void PlayerMainWindow::changeEvent(QEvent *e)
107 QMainWindow::changeEvent(e);
109 case QEvent::LanguageChange:
110 ui->retranslateUi(this);
117 void PlayerMainWindow::playpause()
119 // NB. There is no guarentee that our current state is the real current state.
120 // This is due to the polling frequency and possibility of user interaction directly on the server.
121 // Still this is probably better than nothing and our next real poll will set us straight again.
122 if (PAUSED == mCurrentStatus.state) {
123 mCurrentStatus.state = PLAYING;
124 qDebug() << "pause() from PAUSED";
126 updateUiWithCurrentStatus();
128 else if (PLAYING == mCurrentStatus.state) {
129 mCurrentStatus.state = PAUSED;
130 qDebug() << "pause() from PLAYING";
132 updateUiWithCurrentStatus();
135 // could be STOP or UNKNOWN, either way there is no guarentee we will enter a playing state next.
136 // So don't update the current state or UI
137 // Ideally we would try to find a way to check the current state again but this could lead to an infinite loop!
138 qDebug() << "play() from " << ((STOP == mCurrentStatus.state) ? "STOP" : "UNKNOWN");
142 void PlayerMainWindow::play()
144 mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=pl_play")));
146 void PlayerMainWindow::stop()
148 mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=pl_stop")));
150 void PlayerMainWindow::pause()
152 mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=pl_pause")));
154 void PlayerMainWindow::previous()
156 mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=pl_previous")));
158 void PlayerMainWindow::next()
160 mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=pl_next")));
162 void PlayerMainWindow::fullscreen()
164 mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=fullscreen")));
166 void PlayerMainWindow::volUp()
168 QUrl url = QUrl("http://"+mIp+"/requests/status.xml?command=volume");
169 url.addEncodedQueryItem(QByteArray("val"), QByteArray("%2B20"));
170 mNetManager->get(QNetworkRequest(url));
172 void PlayerMainWindow::volDown()
174 mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=volume&val=-20")));
176 void PlayerMainWindow::volMute()
178 this->mMuted = !this->mMuted;
180 mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=volume&val=0")));
183 mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=volume&val="+QString::number(this->mVolume))));
186 void PlayerMainWindow::slide(int value)
188 mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml?command=seek&val="+QString::number(value)+"%25")));
191 void PlayerMainWindow::showConfig()
194 AccountDialog * dialog = new AccountDialog;
197 mIp= AccountDialog::currentIp();
199 mPlayListMainWindow->init();
200 mBrowserMainWindow->init();
204 void PlayerMainWindow::showAbout()
207 AboutDialog * dialog = new AboutDialog;
212 void PlayerMainWindow::askStatus()
215 QNetworkReply * reply = mNetManager->get(QNetworkRequest(QUrl("http://"+mIp+"/requests/status.xml")));
216 connect(reply,SIGNAL(readyRead()),this,SLOT(parseXmlStatus()));
219 void PlayerMainWindow::parseXmlStatus()
221 QNetworkReply * reply = qobject_cast<QNetworkReply*>(sender());
223 doc.setContent(reply->readAll());
225 QDomElement docElem = doc.documentElement();
226 // Get the raw values
227 int volume = docElem.namedItem("volume").toElement().text().toInt();
228 int length = docElem.namedItem("length").toElement().text().toInt();
229 int time = docElem.namedItem("time").toElement().text().toInt();
230 int position = docElem.namedItem("position").toElement().text().toInt();
231 int random = docElem.namedItem("random").toElement().text().toInt();
232 int loop = docElem.namedItem("loop").toElement().text().toInt();
233 int repeat = docElem.namedItem("repeat").toElement().text().toInt();
234 QString state = docElem.namedItem("state").toElement().text();
235 QDomNode infoNode = docElem.namedItem("information");
236 QDomNode metaInfoNode = infoNode.namedItem("meta-information");
237 QString title = metaInfoNode.namedItem("title").toElement().text().replace("\\\\", "\\");
238 QString artist = metaInfoNode.namedItem("artist").toElement().text();
239 QString album = metaInfoNode.namedItem("album").toElement().text();
240 QString now_playing = metaInfoNode.namedItem("now_playing").toElement().text();
241 QString art_url = metaInfoNode.namedItem("art_url").toElement().text();
242 // Populate the current status structure
243 // now would be a good time to work out if we are a new track / file or not.
244 // key if we are going to look for album art later
245 // for now we check length and title this will require further examination later
246 mCurrentStatus.newtrack = true;
247 if (mCurrentStatus.length == length && !mCurrentStatus.title.isNull() && 0 == QString::compare(mCurrentStatus.title, title)) {
248 mCurrentStatus.newtrack = false;
250 mCurrentStatus.volume = volume;
251 mCurrentStatus.length = length;
252 mCurrentStatus.time = time;
253 mCurrentStatus.position = position;
254 mCurrentStatus.random = (1 == random);
255 mCurrentStatus.loop = (1 == loop);
256 mCurrentStatus.repeat = (1 == repeat);
257 mCurrentStatus.title = title;
258 mCurrentStatus.artist = artist;
259 mCurrentStatus.album = album;
260 mCurrentStatus.nowplaying = now_playing;
261 mCurrentStatus.hasart = (!art_url.isNull() && !art_url.isEmpty());
262 if (!state.isNull() && !state.isEmpty()) {
263 if (0 == QString::compare("playing", state, Qt::CaseInsensitive)) {
264 mCurrentStatus.state = PLAYING;
266 else if (0 == QString::compare("paused", state, Qt::CaseInsensitive)) {
267 mCurrentStatus.state = PAUSED;
269 else if (0 == QString::compare("stop", state, Qt::CaseInsensitive)) {
270 mCurrentStatus.state = STOP;
273 mCurrentStatus.state = UNKNOWN;
277 mCurrentStatus.state = UNKNOWN;
279 // What's our mute status?
280 if (0 < mCurrentStatus.volume) {
281 this->mVolume = mCurrentStatus.volume;
282 this->mMuted = false;
288 updateUiWithCurrentStatus();
292 void PlayerMainWindow::updateUiWithCurrentStatus() {
294 QTime timePosition(0,0,0) ;
295 timePosition = timePosition.addSecs(mCurrentStatus.time);
297 ui->timeLabel->setText(timePosition.toString("h:mm:ss"));
300 if (0 < mCurrentStatus.length) {
301 QTime timeDuration(0,0,0) ;
302 timeDuration = timeDuration.addSecs(mCurrentStatus.length);
304 ui->durationLabel->setText(timeDuration.toString("h:mm:ss"));
307 ui->durationLabel->setText("0:00:00");
311 if (mCurrentStatus.position >= 0 && mCurrentStatus.position <= 100)
312 ui->slider->setValue(mCurrentStatus.position);
314 ui->label->setText(mCurrentStatus.title);
316 if (PLAYING == mCurrentStatus.state) {
317 ui->playpauseButton->setIcon(QIcon::fromTheme("camera_video_pause"));
320 ui->playpauseButton->setIcon(QIcon::fromTheme("camera_playback"));
323 if (mCurrentStatus.newtrack) {
324 // potential actions:
325 // rebuild display layout
326 // retrieve album art
328 // Update the buttons on the playlist window
329 if (NULL != this->mPlayListMainWindow) {
330 this->mPlayListMainWindow->updateUiWithCurrentStatus(& mCurrentStatus);