#include "mainwindow.h" #include "./ui_mainwindow.h" #include "playlistmodel.h" #include "ID3v2Pic.h" #include "FlacPic.h" #include #include #include #include #include #include #include #include #include #include #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) , m_mediaPlayer(new QMediaPlayer(this)) , m_playlistModel(new PlaylistModel(this)) { ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint); this->setAttribute(Qt::WA_TranslucentBackground, true); initConnections(); initUiAndAnimation(); centerWindow(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::commandlinePlayAudioFiles(QList audioFiles) { if (!audioFiles.isEmpty()) { if (audioFiles.count() == 1) { loadPlaylistBySingleLocalFile(audioFiles.first().toLocalFile()); } else { createPlaylist(audioFiles); } m_mediaPlayer->play(); } } void MainWindow::loadPlaylistBySingleLocalFile(const QString &path) { QFileInfo info(path); QDir dir(info.path()); QString currentFileName = info.fileName(); QStringList entryList = dir.entryList({"*.mp3", "*.wav", "*.aiff", "*.ape", "*.flac", "*.ogg", "*.oga"}, QDir::Files | QDir::NoSymLinks, QDir::NoSort); QCollator collator; collator.setNumericMode(true); std::sort(entryList.begin(), entryList.end(), collator); QList urlList; int currentFileIndex = -1; for (int i = 0; i < entryList.count(); i++) { const QString & oneEntry = entryList.at(i); urlList.append(QUrl::fromLocalFile(dir.absoluteFilePath(oneEntry))); if (oneEntry == currentFileName) { currentFileIndex = i; } } QMediaPlaylist * playlist = createPlaylist(urlList); playlist->setCurrentIndex(currentFileIndex); } void MainWindow::closeEvent(QCloseEvent *) { qApp->exit(); } void MainWindow::paintEvent(QPaintEvent * e) { QPainter painter(this); painter.setPen(Qt::NoPen); // Temp bg painter.setBrush(QColor(20, 32, 83)); painter.drawRect(0, 0, width(), height()); painter.setBrush(QBrush(m_bgLinearGradient)); painter.drawRect(0, 0, width(), height()); return QMainWindow::paintEvent(e); } void MainWindow::mousePressEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton && !isMaximized()) { m_clickedOnWindow = true; m_oldMousePos = event->pos(); event->accept(); } return QMainWindow::mousePressEvent(event); } void MainWindow::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton && m_clickedOnWindow) { move(event->globalPos() - m_oldMousePos); event->accept(); } return QMainWindow::mouseMoveEvent(event); } void MainWindow::mouseReleaseEvent(QMouseEvent *event) { m_clickedOnWindow = false; return QMainWindow::mouseReleaseEvent(event); } void MainWindow::dragEnterEvent(QDragEnterEvent *e) { // TODO: file/format filter? e->acceptProposedAction(); } void MainWindow::dropEvent(QDropEvent *e) { QList urls = e->mimeData()->urls(); if (urls.isEmpty()) { return; } QString fileName = urls.first().toLocalFile(); if (fileName.isEmpty()) { return; } // TODO: file/format filter? createPlaylist(urls); m_mediaPlayer->play(); } void MainWindow::loadFile() { QStringList files = QFileDialog::getOpenFileNames(this, tr("Select songs to play"), QDir::homePath(), tr("Audio Files") + " (*.mp3 *.wav *.aiff *.ape *.flac *.ogg *.oga)"); QList urlList; for (const QString & fileName : files) { urlList.append(QUrl::fromLocalFile(fileName)); } createPlaylist(urlList); } /* * The returned QMediaPlaylist* ownership belongs to the internal QMediaPlayer instance. */ QMediaPlaylist *MainWindow::createPlaylist(QList urlList) { if (m_mediaPlayer->playlist()) { m_mediaPlayer->playlist()->disconnect(); } QMediaPlaylist * playlist = new QMediaPlaylist(m_mediaPlayer); for (const QUrl & url : urlList) { bool succ = playlist->addMedia(QMediaContent(url)); if (!succ) { qDebug("!!!!!!!!! break point time !!!!!!!!!"); } } connect(playlist, &QMediaPlaylist::playbackModeChanged, this, [=](QMediaPlaylist::PlaybackMode mode) { switch (mode) { case QMediaPlaylist::CurrentItemInLoop: ui->playbackModeBtn->setIcon(QIcon(":/icons/icons/media-playlist-repeat-song.png")); break; case QMediaPlaylist::Loop: ui->playbackModeBtn->setIcon(QIcon(":/icons/icons/media-playlist-repeat.png")); break; case QMediaPlaylist::Sequential: ui->playbackModeBtn->setIcon(QIcon(":/icons/icons/media-playlist-normal.png")); break; case QMediaPlaylist::Random: ui->playbackModeBtn->setIcon(QIcon(":/icons/icons/media-playlist-shuffle.png")); break; default: break; } }); playlist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop); m_mediaPlayer->setPlaylist(playlist); m_playlistModel->setPlaylist(playlist); return playlist; } void MainWindow::centerWindow() { this->setGeometry( QStyle::alignedRect( Qt::LeftToRight, Qt::AlignCenter, this->size(), qApp->screenAt(QCursor::pos())->geometry() ) ); } void MainWindow::on_closeWindowBtn_clicked() { m_fadeOutAnimation->start(); } void MainWindow::on_playBtn_clicked() { if (m_mediaPlayer->mediaStatus() == QMediaPlayer::NoMedia) { loadFile(); m_mediaPlayer->play(); } else { if (QList {QMediaPlayer::PausedState, QMediaPlayer::StoppedState} .contains(m_mediaPlayer->state())) { m_mediaPlayer->play(); } else { m_mediaPlayer->pause(); } } } QString MainWindow::ms2str(qint64 ms) { QTime duaTime(QTime::fromMSecsSinceStartOfDay(ms)); if (duaTime.hour() > 0) { return duaTime.toString("h:mm:ss"); } else { return duaTime.toString("m:ss"); } } void MainWindow::on_volumeSlider_valueChanged(int value) { if (m_mediaPlayer->isMuted()) { m_mediaPlayer->setMuted(false); } m_mediaPlayer->setVolume(value); } void MainWindow::on_stopBtn_clicked() { m_mediaPlayer->stop(); } void MainWindow::on_playbackSlider_valueChanged(int value) { qint64 currPos = m_mediaPlayer->duration() == 0 ? value : m_mediaPlayer->position() * ui->playbackSlider->maximum() / m_mediaPlayer->duration(); if (qAbs(currPos - value) > 2) { m_mediaPlayer->setPosition(ui->playbackSlider->value() * 1.0 / ui->playbackSlider->maximum() * m_mediaPlayer->duration()); } } void MainWindow::on_prevBtn_clicked() { // QMediaPlaylist::previous() won't work when in CurrentItemInLoop playmode, // and also works not as intended when in other playmode, so do it manually... QMediaPlaylist * playlist = m_mediaPlayer->playlist(); if (playlist) { int index = playlist->currentIndex(); int count = playlist->mediaCount(); m_mediaPlayer->playlist()->setCurrentIndex(index == 0 ? count - 1 : index - 1); } } void MainWindow::on_nextBtn_clicked() { // see also: MainWindow::on_prevBtn_clicked() QMediaPlaylist * playlist = m_mediaPlayer->playlist(); if (playlist) { int index = playlist->currentIndex(); int count = playlist->mediaCount(); m_mediaPlayer->playlist()->setCurrentIndex(index == (count - 1) ? 0 : index + 1); } } void MainWindow::on_volumeBtn_clicked() { m_mediaPlayer->setMuted(!m_mediaPlayer->isMuted()); } void MainWindow::on_minimumWindowBtn_clicked() { this->showMinimized(); } void MainWindow::initUiAndAnimation() { m_bgLinearGradient.setColorAt(0, QColor(255, 255, 255, 25)); // a:0 m_bgLinearGradient.setColorAt(1, QColor(255, 255, 255, 75)); // a:200 m_bgLinearGradient.setStart(0, 0); m_bgLinearGradient.setFinalStop(0, height()); m_fadeOutAnimation = new QPropertyAnimation(this, "windowOpacity", this); m_fadeOutAnimation->setDuration(400); m_fadeOutAnimation->setStartValue(1); m_fadeOutAnimation->setEndValue(0); connect(m_fadeOutAnimation, &QPropertyAnimation::finished, this, &QMainWindow::close); // temp: a playlist for debug... QListView * tmp_listview = new QListView(ui->pluginWidget); tmp_listview->setModel(m_playlistModel); tmp_listview->setGeometry({0,0,490,250}); this->setGeometry({0,0,490,160}); // temp size, hide the playlist thing. } void MainWindow::initConnections() { connect(m_mediaPlayer, &QMediaPlayer::currentMediaChanged, this, [=](const QMediaContent &media) { #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) QUrl fileUrl = media.canonicalUrl(); #else QUrl fileUrl = media.request().url(); #endif // QT_VERSION < QT_VERSION_CHECK(5, 0, 0) ui->titleLabel->setText(fileUrl.fileName()); if (fileUrl.isLocalFile()) { using namespace spID3; using namespace spFLAC; QString filePath(fileUrl.toLocalFile()); if (filePath.endsWith(".mp3")) { if (spID3::loadPictureData(filePath.toLocal8Bit().data())) { QByteArray picData((const char*)spID3::getPictureDataPtr(), spID3::getPictureLength()); ui->coverLabel->setPixmap(QPixmap::fromImage(QImage::fromData(picData))); spID3::freePictureData(); } } else if (filePath.endsWith(".flac")) { if (spFLAC::loadPictureData(filePath.toLocal8Bit().data())) { QByteArray picData((const char*)spFLAC::getPictureDataPtr(), spFLAC::getPictureLength()); ui->coverLabel->setPixmap(QPixmap::fromImage(QImage::fromData(picData))); spFLAC::freePictureData(); } } } }); connect(m_mediaPlayer, &QMediaPlayer::positionChanged, this, [=](qint64 pos) { ui->nowTimeLabel->setText(ms2str(pos)); if (m_mediaPlayer->duration() != 0) { ui->playbackSlider->setSliderPosition(ui->playbackSlider->maximum() * pos / m_mediaPlayer->duration()); } }); connect(m_mediaPlayer, &QMediaPlayer::mutedChanged, this, [=](bool muted) { if (muted) { ui->volumeBtn->setIcon(QIcon(":/icons/icons/audio-volume-muted.png")); } else { ui->volumeBtn->setIcon(QIcon(":/icons/icons/audio-volume-high.png")); } }); connect(m_mediaPlayer, &QMediaPlayer::durationChanged, this, [=](qint64 dua) { ui->totalTimeLabel->setText(ms2str(dua)); }); connect(m_mediaPlayer, &QMediaPlayer::stateChanged, this, [=](QMediaPlayer::State newState) { switch (newState) { case QMediaPlayer::PlayingState: ui->playBtn->setIcon(QIcon(":/icons/icons/media-playback-pause.png")); break; case QMediaPlayer::StoppedState: case QMediaPlayer::PausedState: ui->playBtn->setIcon(QIcon(":/icons/icons/media-playback-start.png")); break; } }); connect(m_mediaPlayer, &QMediaPlayer::volumeChanged, this, [=](int vol) { ui->volumeSlider->setValue(vol); }); connect(m_mediaPlayer, static_cast(&QMediaPlayer::error), this, [=](QMediaPlayer::Error error) { switch (error) { default: break; } qDebug("%s aaaaaaaaaaaaa", m_mediaPlayer->errorString().toUtf8().data()); }); } void MainWindow::on_playbackModeBtn_clicked() { QMediaPlaylist * playlist = m_mediaPlayer->playlist(); if (!playlist) return; switch (playlist->playbackMode()) { case QMediaPlaylist::CurrentItemInLoop: playlist->setPlaybackMode(QMediaPlaylist::Loop); break; case QMediaPlaylist::Loop: playlist->setPlaybackMode(QMediaPlaylist::Sequential); break; case QMediaPlaylist::Sequential: playlist->setPlaybackMode(QMediaPlaylist::Random); break; case QMediaPlaylist::Random: playlist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop); break; default: break; } }