3 #include <QInputDialog>
5 #include "mainwindow.h"
8 //#define AVOID_INPUT_DIALOG 0
10 MainWindow::MainWindow()
11 : plman (this), settings (tr ("TomAmp"), "TomAmp")
13 audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
14 mediaObject = new Phonon::MediaObject(this);
16 mediaObject->setTickInterval(1000);
17 connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(tick(qint64)));
18 connect(mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
19 this, SLOT(stateChanged(Phonon::State,Phonon::State)));
20 connect(mediaObject, SIGNAL(currentSourceChanged(Phonon::MediaSource)),
21 this, SLOT(sourceChanged(Phonon::MediaSource)));
22 connect(mediaObject, SIGNAL(aboutToFinish()), this, SLOT(aboutToFinish()));
23 connect (&plman, SIGNAL (playlistChanged (int)), this, SLOT (playlistChanged(int)));
24 connect (&plman, SIGNAL (itemUpdated(int)), this, SLOT (itemUpdated (int)));
26 Phonon::createPath(mediaObject, audioOutput);
29 repeat = settings.value("repeat", false).toBool();
30 shuffle = settings.value("shuffle", false).toBool();
35 timeLcd->display("00:00");
36 plman.addStringList(settings.value("lastPlaylist").toStringList());
37 // shuffleList = settings.value("shuffleList", QList<int>()).toList();
38 QList<QVariant> tmp = settings.value("shuffleList").toList();
39 for (int i = 0; i < tmp.size (); ++i)
40 shuffleList.append (tmp[i].toInt());
41 if (!shuffleList.size())
43 int curind = settings.value("currentIndex", -1).toInt ();
46 audioOutput->setVolume(settings.value("volume", .5).toReal());
49 MainWindow::~MainWindow()
51 settings.setValue("shuffle", shuffle);
52 settings.setValue("repeat", repeat);
53 settings.setValue("lastPlaylist", plman.playlistStrings());
54 settings.setValue("volume", audioOutput->volume());
55 settings.setValue("currentIndex", plman.indexOf(mediaObject->currentSource()));
57 for (int i = 0; i < shuffleList.size(); ++i)
59 settings.setValue("shuffleList", tmp);
62 void MainWindow::addFiles()
64 QString folder = settings.value("LastFolder").toString();
66 folder = QDesktopServices::storageLocation(QDesktopServices::MusicLocation);
67 QStringList files = QFileDialog::getOpenFileNames(this, tr("Select Files To Add"),
73 QString dir = QFileInfo (files[0]).absoluteDir().absolutePath();
74 settings.setValue("LastFolder", dir);
76 foreach (QString string, files)
78 toadd.append (string);
80 plman.addStringList(toadd);
83 void MainWindow::addFolder()
85 QString folder = settings.value("LastFolder").toString();
87 folder = QDesktopServices::storageLocation(QDesktopServices::MusicLocation);
88 QString dir = QFileDialog::getExistingDirectory(this,
89 tr("Select Directory To Add"),
93 QStringList files = QDir (dir).entryList(filters, QDir::AllDirs);
95 files.removeAll("..");
97 bool recursive = false;
99 recursive = QMessageBox::question(this, "Add all folders", "Subfolders have been detected, add everything?", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes;
100 plman.parseAndAddFolder(dir, recursive);
104 void MainWindow::addUrl()
106 #ifdef AVOID_INPUT_DIALOG
107 QString url = "http://war.str3am.com:7970";
109 QString url = QInputDialog::getText(this, "Get URL", "Please type in the stream URL");
113 plman.addStringList(toadd);
117 void MainWindow::about()
119 QMessageBox::information(this, tr("About TomAmp v0.1"),
120 tr("TomAmp is a simple playlist-based music player.\n\n"
121 "(c) 2010 Tamas Marki <tmarki@gmail.com>\n\n"
122 "Please send comments and bug reports to the above e-mail address.\n\n"
123 "Icons by deleket (http://www.deleket.com)"));
126 void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState */)
128 qDebug () << "State: " << newState;
131 case Phonon::ErrorState:
132 if (mediaObject->errorType() == Phonon::FatalError)
134 // QMessageBox::warning(this, tr("Fatal Error"),
135 // mediaObject->errorString() + mediaObject->currentSource().fileName() + ", " + mediaObject->currentSource().url().toString());
139 // QMessageBox::warning(this, tr("Error"),
140 // mediaObject->errorString());
144 case Phonon::PlayingState:
145 setWindowTitle(mediaObject->metaData().value("TITLE") + " - TomAmp");
146 pauseAction->setVisible(true);
147 playAction->setVisible (false);
148 playAction->setEnabled(false);
149 pauseAction->setEnabled(true);
150 stopAction->setEnabled(true);
152 case Phonon::StoppedState:
153 stopAction->setEnabled(false);
154 playAction->setEnabled(true);
155 pauseAction->setVisible(false);
156 playAction->setVisible(true);
157 pauseAction->setEnabled(false);
158 timeLcd->display("00:00");
160 case Phonon::PausedState:
161 pauseAction->setEnabled(false);
162 stopAction->setEnabled(true);
163 pauseAction->setVisible(false);
164 playAction->setVisible(true);
165 playAction->setEnabled(true);
166 qDebug () << "Queue size: " << mediaObject->queue().size ();
167 if (mediaObject->queue().size ())
169 mediaObject->setCurrentSource(mediaObject->queue()[0]);
170 musicTable->selectRow(plman.indexOf(mediaObject->currentSource()));
173 mediaObject->clearQueue();
175 case Phonon::BufferingState:
176 qDebug () << "Buffering";
183 void MainWindow::next()
185 bool wasPlaying = (mediaObject->state () == Phonon::PlayingState);
186 if (mediaObject->state () == Phonon::ErrorState)
188 qDebug () << "NEXT, repeat=" << repeat << ", shuffle=" << shuffle;
189 int index = plman.indexOf(mediaObject->currentSource());
190 qDebug () << "Current index is " << index;
193 qDebug () << "Shuffle next " << index;
194 index = shuffleList.indexOf(plman.indexOf(mediaObject->currentSource())) + 1;
195 while (index < shuffleList.size () && !plman.getItem(shuffleList[index]).playable)
198 qDebug () << "Index increase a " << index;
200 qDebug () << "Shuffle next 2 " << index;
201 if (index < shuffleList.size ())
208 while ((index) < shuffleList.size () && !plman.getItem(shuffleList[index]).playable)
210 qDebug () << "Index increase 2a " << index;
215 if (index >= shuffleList.size ())
222 qDebug () << "Normal next";
223 while ((index) < plman.size () && !plman.getItem(index).playable)
226 qDebug () << "Index increase " << index;
228 qDebug () << "Normal next 2 " << index;
229 if (index < plman.size())
235 qDebug () << "Repeat on";
237 while ((index) < plman.size () && !plman.getItem(index).playable)
240 qDebug () << "Index increase " << index;
244 if (index >= shuffleList.size ())
249 qDebug () << "wasPlaying: " << wasPlaying << ", playbutton visible: " << playAction->isVisible();
252 void MainWindow::setItem(int i)
254 int curInd = plman.indexOf(mediaObject->currentSource());
255 for (int j = 0; j < 3 && curInd >= 0 && curInd < shuffleList.size (); ++j)
257 QTableWidgetItem* item = musicTable->item(curInd, j);
260 QFont font = item->font();
262 font.setItalic(false);
266 if (i < plman.size() && i >= 0)
270 for (int j = 0; j < 3; ++j)
272 QTableWidgetItem* item = musicTable->item(shuffleList[i], j);
275 QFont font = item->font();
277 font.setItalic(true);
281 mediaObject->setCurrentSource(plman.at (shuffleList[i]));
282 musicTable->selectRow (shuffleList[i]);
286 for (int j = 0; j < 3; ++j)
288 QTableWidgetItem* item = musicTable->item(i, j);
291 QFont font = item->font();
293 font.setItalic(true);
297 mediaObject->setCurrentSource(plman.at(i));
298 musicTable->selectRow (i);
303 void MainWindow::previous()
305 bool wasPlaying = (mediaObject->state () == Phonon::PlayingState);
306 if (mediaObject->state () == Phonon::ErrorState)
308 qDebug () << "PREVIOUS, repeat=" << repeat << ", shuffle=" << shuffle;
309 int index = plman.indexOf(mediaObject->currentSource());
310 qDebug () << "Current index is " << index;
313 qDebug () << "Shuffle next";
314 index = shuffleList.indexOf(plman.indexOf(mediaObject->currentSource())) - 1;
315 while (index >= 0 && !plman.getItem(shuffleList[index]).playable)
318 qDebug () << "Index increase a " << index;
320 qDebug () << "Shuffle next 2 " << index;
327 index = plman.size () - 1;
328 while (index >= 0 && !plman.getItem(shuffleList[index]).playable)
330 qDebug () << "Index increase 2a " << index;
342 qDebug () << "Normal next";
343 while ((index) >= 0 && !plman.getItem(index).playable)
346 qDebug () << "Index increase " << index;
348 qDebug () << "Normal next 2 " << index;
355 qDebug () << "Repeat on";
356 index = plman.size() - 1;
357 while ((index) >= 0 && !plman.getItem(index).playable)
360 qDebug () << "Index increase " << index;
369 qDebug () << "wasPlaying: " << wasPlaying << ", playbutton visible: " << playAction->isVisible();
371 /* bool wasPlaying = (mediaObject->state () == Phonon::PlayingState);
372 int index = plman.indexOf(mediaObject->currentSource()) - 1;
375 index = shuffleList.indexOf(plman.indexOf(mediaObject->currentSource())) - 1;
378 mediaObject->setCurrentSource(plman.at (shuffleList[index]));
382 mediaObject->setCurrentSource(plman.at (shuffleList[shuffleList.size() - 1]));
390 mediaObject->setCurrentSource(plman.at(index));
394 mediaObject->setCurrentSource(plman.at(plman.size() - 1));
398 mediaObject->play();*/
402 void MainWindow::tick(qint64 time)
404 QTime displayTime(0, (time / 60000) % 60, (time / 1000) % 60);
406 timeLcd->display(displayTime.toString("mm:ss"));
409 void MainWindow::tableClicked(int row, int /* column */)
411 // bool wasPlaying = mediaObject->state() == Phonon::PlayingState;
413 /* mediaObject->stop();
414 mediaObject->clearQueue();*/
416 if (row >= plman.size())
420 while (index < shuffleList.size () && !plman.getItem(index).playable)
424 if (plman.size() > index)
427 index = shuffleList.indexOf(index);
434 while (index < plman.size () && !plman.getItem(index).playable)
438 if (plman.size() > index)
441 index = shuffleList.indexOf(index);
449 void MainWindow::sourceChanged(const Phonon::MediaSource &source)
451 musicTable->selectRow(plman.indexOf(source));
452 timeLcd->display("00:00");
456 void MainWindow::aboutToFinish()
458 qDebug () << "Abouttotfinish";
459 int index = plman.indexOf(mediaObject->currentSource()) + 1;
462 index = shuffleList.indexOf(plman.indexOf(mediaObject->currentSource())) + 1;
463 if (index < shuffleList.size ())
465 mediaObject->enqueue(plman.at (shuffleList[index]));
469 mediaObject->enqueue(plman.at (shuffleList[0]));
475 if (plman.size() > index)
477 mediaObject->enqueue(plman.at(index));
478 qDebug () << "Enqueue " << index << " pfm " << mediaObject->prefinishMark();
482 mediaObject->enqueue(plman.at(0));
483 qDebug () << "Enqueue " << 0 << " pfm " << mediaObject->prefinishMark();
488 void MainWindow::finished()
490 qDebug () << "Finished";
493 void MainWindow::setupActions()
495 playAction = new QAction(QIcon (QPixmap (":images/play")), tr("Play"), this);
496 playAction->setShortcut(tr("Crl+P"));
497 playAction->setDisabled(true);
498 pauseAction = new QAction(QIcon (QPixmap (":images/pause")), tr("Pause"), this);
499 pauseAction->setShortcut(tr("Ctrl+A"));
500 pauseAction->setDisabled(true);
501 pauseAction->setVisible(false);
502 stopAction = new QAction(QIcon (QPixmap (":images/stop")), tr("Stop"), this);
503 stopAction->setShortcut(tr("Ctrl+S"));
504 stopAction->setDisabled(true);
505 nextAction = new QAction(QIcon (QPixmap (":images/next")), tr("Next"), this);
506 nextAction->setShortcut(tr("Ctrl+N"));
507 previousAction = new QAction(QIcon (QPixmap (":images/previous")), tr("Previous"), this);
508 previousAction->setShortcut(tr("Ctrl+R"));
509 repeatAction = new QAction(QIcon (QPixmap (":images/repeat")), tr("Repeat"), this);
510 repeatAction->setCheckable(true);
511 repeatAction->setChecked(repeat);
512 repeatAction->setShortcut(tr("Ctrl+I"));
513 shuffleAction = new QAction(QIcon (QPixmap (":images/shuffle")), tr("Shuffle"), this);
514 shuffleAction->setCheckable(true);
515 shuffleAction->setChecked(shuffle);
516 shuffleAction->setShortcut(tr("Ctrl+H"));
517 volumeAction = new QAction(QIcon (QPixmap (":images/volume")), tr("Volume"), this);
518 volumeAction->setCheckable(true);
519 volumeAction->setShortcut(tr("Ctrl+V"));
520 addFilesAction = new QAction(tr("Add &File"), this);
521 addFilesAction->setShortcut(tr("Ctrl+F"));
522 addFoldersAction = new QAction(tr("Add F&older"), this);
523 addFoldersAction->setShortcut(tr("Ctrl+O"));
524 addUrlAction = new QAction(tr("Add &Url"), this);
525 addUrlAction->setShortcut(tr("Ctrl+U"));
526 savePlaylistAction = new QAction (tr("Sa&ve Playlist"), this);
527 savePlaylistAction->setShortcut(tr ("Ctrl+V"));
528 loadPlaylistAction = new QAction (tr("&Load Playlist"), this);
529 loadPlaylistAction->setShortcut(tr("Ctrl+L"));
530 clearPlaylistAction = new QAction (tr("&Clear Playlist"), this);
531 clearPlaylistAction->setShortcut(tr("Ctrl+C"));
532 exitAction = new QAction(tr("E&xit"), this);
533 exitAction->setShortcut(tr("Ctrl+X"));
534 aboutAction = new QAction(tr("A&bout"), this);
535 aboutAction->setShortcut(tr("Ctrl+B"));
536 aboutQtAction = new QAction(tr("About &Qt"), this);
537 aboutQtAction->setShortcut(tr("Ctrl+Q"));
539 connect(playAction, SIGNAL(triggered()), mediaObject, SLOT(play()));
540 connect(pauseAction, SIGNAL(triggered()), mediaObject, SLOT(pause()) );
541 connect(stopAction, SIGNAL(triggered()), mediaObject, SLOT(stop()));
542 connect(repeatAction, SIGNAL(triggered()), this, SLOT(repeatToggle()));
543 connect(shuffleAction, SIGNAL(triggered()), this, SLOT(shuffleToggle()));
544 connect(volumeAction, SIGNAL(triggered()), this, SLOT(volumeToggle()));
545 connect(addFilesAction, SIGNAL(triggered()), this, SLOT(addFiles()));
546 connect(addFoldersAction, SIGNAL(triggered()), this, SLOT(addFolder()));
547 connect(addUrlAction, SIGNAL(triggered()), this, SLOT(addUrl()));
548 connect (savePlaylistAction, SIGNAL (triggered()), this, SLOT (savePlaylist()));
549 connect (loadPlaylistAction, SIGNAL (triggered()), this, SLOT (loadPlaylist()));
550 connect (clearPlaylistAction, SIGNAL (triggered()), &plman, SLOT (clearPlaylist()));
551 connect (nextAction, SIGNAL(triggered()), this, SLOT(next()));
552 connect (previousAction, SIGNAL(triggered()), this, SLOT(previous()));
553 connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
554 connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
555 connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
559 void MainWindow::repeatToggle ()
562 qDebug() << "Repeat toggled to " << repeat;
563 settings.setValue("repeat", QVariant (repeat));
566 void MainWindow::shuffleToggle ()
569 settings.setValue("shuffle", QVariant (shuffle));
572 void MainWindow::volumeToggle ()
574 qDebug () << "Volumetoggle: " << volumeAction->isChecked();
575 volumeSlider->setVisible(volumeAction->isChecked());
578 void MainWindow::play()
584 void MainWindow::setupMenus()
586 QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
587 fileMenu->addAction(addFilesAction);
588 fileMenu->addAction(addFoldersAction);
589 fileMenu->addAction(addUrlAction);
590 fileMenu->addSeparator();
591 fileMenu->addAction(savePlaylistAction);
592 fileMenu->addAction(loadPlaylistAction);
593 fileMenu->addAction(clearPlaylistAction);
594 // fileMenu->addAction(exitAction);
596 QMenu *aboutMenu = menuBar()->addMenu(tr("&Help"));
597 aboutMenu->addAction(aboutAction);
598 aboutMenu->addAction(aboutQtAction);
601 void MainWindow::setupUi()
603 QToolBar *bar = new QToolBar;
605 bar->setOrientation(Qt::Vertical);
606 bar->setStyleSheet("padding:7px");
607 //bar->addAction(volumeAction);
609 seekSlider = new Phonon::SeekSlider(this);
610 seekSlider->setMediaObject(mediaObject);
612 volumeSlider = new Phonon::VolumeSlider(this);
613 volumeSlider->setAudioOutput(audioOutput);
614 volumeSlider->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
615 volumeSlider->setOrientation(Qt::Horizontal);
616 volumeSlider->setMuteVisible(false);
617 // volumeAddedAction = bar->addWidget(volumeSlider);
618 // volumeAddedAction->setVisible(false);
619 bar->addAction(playAction);
620 bar->addAction(pauseAction);
621 bar->addAction(stopAction);
622 bar->addAction(repeatAction);
623 bar->addAction(shuffleAction);
624 bar->addAction(nextAction);
625 bar->addAction(previousAction);
627 /* QLabel *volumeLabel = new QLabel;
628 volumeLabel->setPixmap(QPixmap("images/volume.png"));*/
631 palette.setBrush(QPalette::Light, Qt::darkGray);*/
633 timeLcd = new QLCDNumber;
634 // timeLcd->setPalette(palette);
637 headers << tr("Artist") << tr("Title") << tr("Album");
639 musicTable = new QTableWidget(0, 3);
640 musicTable->setHorizontalHeaderLabels(headers);
641 musicTable->setSelectionMode(QAbstractItemView::SingleSelection);
642 musicTable->setSelectionBehavior(QAbstractItemView::SelectRows);
643 connect(musicTable, SIGNAL(cellDoubleClicked(int,int)),
644 this, SLOT(tableClicked(int,int)));
645 connect(musicTable, SIGNAL(cellClicked(int,int)),
646 this, SLOT(cellClicked(int,int)));
647 musicTable->setSelectionBehavior(QAbstractItemView::SelectRows);
649 QHBoxLayout *seekerLayout = new QHBoxLayout;
650 QToolBar* bar2 = new QToolBar;
651 bar2->addAction(volumeAction);
652 seekerLayout->addWidget(bar2);
653 seekerLayout->addWidget(volumeSlider);
654 seekerLayout->addWidget(seekSlider);
655 seekerLayout->addWidget(timeLcd);
657 QVBoxLayout *playbackLayout = new QVBoxLayout;
658 volumeSlider->hide ();
659 playbackLayout->addWidget(bar);
660 // playbackLayout->addStretch();
661 // playbackLayout->addWidget(volumeSlider);
662 // playbackLayout->addWidget(volumeLabel);
664 QVBoxLayout *seekAndTableLayout = new QVBoxLayout;
666 seekAndTableLayout->addWidget(musicTable);
667 seekAndTableLayout->addLayout(seekerLayout);
669 QHBoxLayout *mainLayout = new QHBoxLayout;
670 mainLayout->addLayout(seekAndTableLayout);
671 mainLayout->addLayout(playbackLayout);
673 QWidget *widget = new QWidget;
674 widget->setLayout(mainLayout);
676 setCentralWidget(widget);
677 setWindowTitle("TomAmp");
678 qDebug () << "cucc: " << musicTable->columnWidth(1);
681 void MainWindow::cellClicked(int /*row*/, int)
683 /*if (mediaObject->state() == Phonon::PlayingState)
685 int index = plman.indexOf(mediaObject->currentSource());
688 musicTable->selectRow(index);
691 else if (row < plman.size())
693 mediaObject->setCurrentSource(plman.at(row));
694 shuffleList.removeAll(row);
695 shuffleList.insert(0, row);
696 qDebug () << shuffleList;
700 void MainWindow::setupShuffleList()
703 int index = plman.indexOf(mediaObject->currentSource());
706 for (int i = 0; i < plman.size(); ++i)
712 shuffleList.append (index);
715 int ind = qrand () % tmp.size();
716 shuffleList.append(tmp[ind]);
719 qDebug () << shuffleList;
720 qDebug () << shuffleList;
723 void MainWindow::savePlaylist ()
725 QString filename = QFileDialog::getSaveFileName(this, tr("Please select file name"), "", "Playlist Files (*.m3u)");
726 plman.loadPlaylist(filename);
729 void MainWindow::loadPlaylist ()
731 QString filename = QFileDialog::getOpenFileName(this, tr("Select playlist file to load"), "", "*.m3u");
732 plman.loadPlaylist (filename);
735 void MainWindow::playlistChanged(int from)
737 while (musicTable->rowCount() > from)
739 musicTable->removeRow(musicTable->rowCount () - 1);
741 for (int i = from; i < plman.size (); ++i)
743 int currentRow = musicTable->rowCount();
744 musicTable->insertRow(currentRow);
745 setRowFromItem (currentRow, plman.getItem(i));
750 void MainWindow::setRowFromItem (int row, const PlaylistItem& item)
752 if (row >= musicTable->rowCount())
754 if (item.artist.isEmpty() && item.title.isEmpty())
756 QTableWidgetItem *item1 = new QTableWidgetItem(item.uri);
757 item1->setFlags(item1->flags() ^ Qt::ItemIsEditable);
758 musicTable->setItem(row, 1, item1);
762 QTableWidgetItem *item1 = new QTableWidgetItem(item.artist);
763 item1->setFlags(item1->flags() ^ Qt::ItemIsEditable);
764 musicTable->setItem(row, 0, item1);
765 QTableWidgetItem *item2 = new QTableWidgetItem(item.title);
766 item2->setFlags(item2->flags() ^ Qt::ItemIsEditable);
767 musicTable->setItem(row, 1, item2);
768 QTableWidgetItem *item3 = new QTableWidgetItem(item.album);
769 item3->setFlags(item3->flags() ^ Qt::ItemIsEditable);
770 musicTable->setItem(row, 2, item3);
774 void MainWindow::itemUpdated(int index)
776 setRowFromItem (index, plman.getItem(index));
777 if (plman.indexOf(mediaObject->currentSource()) < 0 && plman.getItem (index).playable)
778 mediaObject->setCurrentSource(plman.getItem(index).source);