標籤:c++ 音頻播放
功能介紹:
MP3播放器
構思過程:滿足基本的播放要求(播放/暫停,快進,快退),帶有歌詞顯示,標籤顯示,帶曲目列表,支援中文
用到的工具(平台:Windows XP SP3):
程式設計語言:C++
表徵圖製作:Photo shop
音頻檔案標籤庫:mediaInfo(第三方庫)
標籤編碼轉換:sqlite3資料庫及sqlite3 C++庫(提前已經將對應的unicode和gbk編碼用C++錄入sqlite3資料庫,過程如果遇到需要,則直接查表調用即可)
檔案目錄:
程式運行介面:
初始狀態
添加多個檔案狀態
列表橫向擺放
主要代碼部分
/* *功能: 音頻播放器 * KAKASI ([email protected]) *時間: 2014-6-1 *版本: V1.0 * */#include "musicPlayer.h"#include <QHBoxLayout>#include <QVBoxLayout>#include <QGridLayout>#include <QPixmap>#include <QBitmap>#include <QPainter>#include <QIcon>#include <QFile>#include <QTextStream>#include <QPushButton>#include <QMediaMetaData>#include <QDebug>#include <QLibrary>#include <stdio.h>#include <QFileInfo>#include <QFileDialog>#include <QLocale>#include <iostream>#include <QByteArray>#include <iostream>#include <QByteArray>#include <string.h>#include <stdlib.h>#include <locale.h>#include <bitset>#include <iomanip>#include <QTextCodec>#include "QMediaInfo.h"using namespace std;#define cout qDebug()MusicPlayer::MusicPlayer(QWidget *parent) :QWidget(parent){ //some information init this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); isMouseDown = false; QPushButton *listBtn = new QPushButton("L"); listBtn->setMaximumSize(20,20); connect(listBtn, SIGNAL(clicked()), SLOT(showList())); listBtn->setStyleSheet("background:gray"); QPushButton *loadBtn = new QPushButton("O"); loadBtn->setMaximumSize(20,20); connect(loadBtn, SIGNAL(clicked()), SLOT(loadMusics())); loadBtn->setStyleSheet("background:gray"); QPushButton *minBtn = new QPushButton("-"); minBtn->setMaximumSize(20,20); connect(minBtn, SIGNAL(clicked()), SLOT(setMin())); minBtn->setStyleSheet("background:gray"); QPushButton *exitBtn = new QPushButton("X"); exitBtn->setMaximumSize(30,20); connect(exitBtn, SIGNAL(clicked()),SLOT(close())); exitBtn->setStyleSheet("background:gray; text-align:top"); QHBoxLayout *titleLayout = new QHBoxLayout; titleLayout->addStretch(); titleLayout->addWidget(listBtn,0,Qt::AlignTop); titleLayout->addWidget(loadBtn,0,Qt::AlignTop); titleLayout->addWidget(minBtn,0,Qt::AlignTop); titleLayout->addWidget(exitBtn,0,Qt::AlignTop); titleLayout->setSpacing(0); titleLayout->setContentsMargins(0, 0, 0, 0); //layout musicNameLabel = new MyLabel(); musicNameLabel->setMinimumWidth(200); musicNameLabel->setText("Take Me Away"); musicNameLabel->setStyleSheet("font-size:23px; font-family: 隸書; color:white"); authorLabel = new MyLabel(); authorLabel->setText("Avril"); authorLabel->setStyleSheet("font-size:14px; font-family:隸書; color:white"); timeLabel = new MyLabel(); totalTime = 302; timeLabel->setText(tr("T: <span style='color:Coral'>%1</span> / %2").arg(getTimeStr(0)).arg(getTimeStr(totalTime))); timeLabel->setStyleSheet("font-size:14px; font-family:隸書;color:white"); volLabel = new MyLabel; volLabel->setText(tr("V:%1").arg("30%")); volLabel->setStyleSheet("font-size:14px; font-family:隸書; color:white"); QHBoxLayout *timeAndVolLabel = new QHBoxLayout; timeAndVolLabel->addWidget(volLabel); timeAndVolLabel->addStretch(); timeAndVolLabel->addWidget(timeLabel); prevLabel = new MyLabel; playOrPauseLabel = new MyLabel; nextLabel = new MyLabel; connect(playOrPauseLabel, SIGNAL(clicked()), SLOT(playOrPause())); connect(nextLabel, SIGNAL(clicked()), SLOT(next())); connect(prevLabel, SIGNAL(clicked()), SLOT(prev())); QPixmap img1("images/prev3.png"); QPixmap img2("images/play.png"); QPixmap img3("images/next3.png"); prevLabel->setPixmap(img1.scaled(40,40)); playOrPauseLabel->setPixmap(img2.scaled(60,60)); nextLabel->setPixmap(img3.scaled(40,40)); prevLabel->resize(40,40); playOrPauseLabel->resize(60,60); nextLabel->resize(40,40); prevLabel->setStyleSheet("border-style:flat;"); playOrPauseLabel->setStyleSheet("border-style:flat"); nextLabel->setStyleSheet("border-style:flat"); QString smallStyleStr = "width:40px; height:40px; "; QString bigStyleStr = "width:60px; height:60px; "; prevLabel->setStyleSheet(smallStyleStr); playOrPauseLabel->setStyleSheet(bigStyleStr); nextLabel->setStyleSheet(smallStyleStr); picLabel = new MyLabel(); picLabel->resize(85,85); picLabel->setStyleSheet("margin-left:6px;margin-right:10px;"); QPixmap pic("images/logo.png"); picLabel->setPixmap(pic); QHBoxLayout *picLayout = new QHBoxLayout; picLayout->addWidget(picLabel); space = new MyLabel; space->setText("<hr>"); currentLRC = new MyLabel("<center> </center>"); currentLRC->setStyleSheet("font-size:25px; font-family:隸書;color:DeepSkyBlue;"); nextLRC = new MyLabel("<center> </center>"); nextLRC->setStyleSheet("font-size:15px; font-family:隸書; color:LightGrey;"); progressSlider = new QSlider(Qt::Horizontal); progressSlider->setRange(0,totalTime); connect(progressSlider, SIGNAL(sliderMoved(int)), SLOT(setPosition(int))); connect(progressSlider, SIGNAL(sliderReleased()), SLOT(setPosition())); volSlider = new QSlider(Qt::Horizontal); volSlider->setRange(0,100); volSlider->setValue(30); connect(volSlider, SIGNAL(valueChanged(int)), SLOT(changeVol(int))); QFile file("qss/style1.qss"); file.open(QFile::ReadOnly); volSlider->setStyleSheet(file.readAll()); file.close(); file.setFileName("qss/style2.qss"); file.open(QFile::ReadOnly); progressSlider->setStyleSheet(file.readAll()); progressSlider->setMinimumWidth(240); QHBoxLayout *slider = new QHBoxLayout; slider->addWidget(volSlider); slider->addStretch(); slider->addWidget(progressSlider); QVBoxLayout *midLayout = new QVBoxLayout(); midLayout->addWidget(musicNameLabel); midLayout->addWidget(authorLabel); midLayout->addLayout(timeAndVolLabel); QHBoxLayout *operationLayout = new QHBoxLayout(); operationLayout->addWidget(prevLabel, 0,Qt::AlignRight); operationLayout->addWidget(playOrPauseLabel, 0, Qt::AlignRight); operationLayout->addWidget(nextLabel, 0, Qt::AlignRight); QHBoxLayout *topLayout = new QHBoxLayout; topLayout->addLayout(midLayout); topLayout->addLayout(operationLayout); QVBoxLayout *rightLayout = new QVBoxLayout; rightLayout->addLayout(topLayout); rightLayout->addLayout(slider); QVBoxLayout *lrcLayout = new QVBoxLayout; lrcLayout->addWidget(currentLRC); lrcLayout->addWidget(nextLRC); QHBoxLayout *mainLayout1 = new QHBoxLayout(); mainLayout1->addLayout(picLayout); mainLayout1->addLayout(rightLayout); QVBoxLayout *mainLayout2 = new QVBoxLayout(); mainLayout2->addLayout(titleLayout); mainLayout2->addLayout(mainLayout1); mainLayout2->addWidget(space); mainLayout2->addLayout(lrcLayout); mainLayout2->setSpacing(0); mainLayout2->setContentsMargins(5,0,15,15); this->setLayout(mainLayout2); this->resize(this->sizeHint()); //important for setRounded(bool) setAttribute(Qt::WA_TranslucentBackground, true); setRounded(true); isPlaying = false; listUi = 0; list = new QStringList; playerList = new QMediaPlaylist; playerList->setCurrentIndex(0); playerList->setPlaybackMode(QMediaPlaylist::Loop); player = new QMediaPlayer; player->setPlaylist(playerList); connect(player,SIGNAL(positionChanged(qint64)), SLOT(positionChange(qint64))); connect(player,SIGNAL(durationChanged(qint64)), SLOT(durationChange(qint64))); volSlider->setValue(player->volume()); createActions(); lrc = new QMap<int,QString>; updateInfo();}void MusicPlayer::closeEvent(QCloseEvent *event){ if (listUi != 0) listUi->close(); event->accept();}//顯示曲目列表void MusicPlayer::showList(){ if (listUi == 0) { listUi = new MediaList(this->sizeHint(), this->pos(), this); listUi->show(); return; } if (listUi->isHidden()) { listUi->show(); } else { listUi->hide(); }}//開啟音頻檔案void MusicPlayer::loadMusics(){ QStringList files = QFileDialog::getOpenFileNames( this, "Select one or more files to open", "/home", "musics (*.mp3 *.wma *.wav)"); int begin = list->length(); if (!files.isEmpty()) { QString str; foreach (str, files) { list->append(str); playerList->addMedia(QUrl::fromLocalFile(list->last())); } playerList->setCurrentIndex(begin); updateInfo(); if (listUi == 0) { listUi = new MediaList(this->sizeHint(), this->pos(), this); } if (listUi != 0) { listUi->addFiles(files); } } //歌詞初始化 initLrc(); player->play(); QPixmap img(("images/pause.png")); playOrPauseLabel->setPixmap(img.scaled(60,60));}//任意地區右鍵菜單void MusicPlayer::contextMenuEvent(QContextMenuEvent *event){ menu->clear(); menu->addAction(openAction); menu->addAction(exitAction); menu->exec(QCursor::pos()); event->accept();}//void MusicPlayer::createActions(){ menu = new QMenu(this); openAction = new QAction("open",this); exitAction = new QAction("exit",this);}//更新介面資訊void MusicPlayer::updateInfo(){ QString title; QString author; QFileInfo f; if (!list->empty()) { QString fileName = list->at(playerList->currentIndex()); info = new QMediaInfo(fileName); f.setFile(fileName); if (f.suffix().toUpper() == "MP3") { title = info->getInfo("Title",true); author = info->getInfo("Performer",true); } else { title = info->getInfo("Title"); author = info->getInfo("Performer"); } title = f.baseName(); //cout << title << author; delete info; } title.truncate(8); if (title.length() > 8) title += ".."; if (title.isEmpty()) title = "Title:Unknown"; if (author.isEmpty()) author = "Author:Unknown"; musicNameLabel->setText(title); authorLabel->setText(author); curLrc = ""; nextLrcStr = ""; currentLRC->setText("<center>" + curLrc +"</center>"); nextLRC->setText("<center>" + nextLrcStr +"</center>"); //歌詞初始化 initLrc();}//下一首void MusicPlayer::next(){ playerList->next(); //qDebug()<<playerList->currentIndex(); updateInfo(); //歌詞初始化 initLrc();}//上一首void MusicPlayer::prev(){ playerList->previous(); updateInfo(); //歌詞初始化 initLrc();}//時間更新void MusicPlayer::durationChange(qint64 duration){ totalTime = duration; progressSlider->setRange(0, duration); timeLabel->setText(tr("T: <span style='color:Coral'>%1</span> / %2").arg(getTimeStr(0)).arg(getTimeStr(totalTime)));}//進度更新void MusicPlayer::positionChange(qint64 pos){ if (!progressSlider->isSliderDown()) progressSlider->setValue(pos); timeLabel->setText(tr("T: <span style='color:Coral'>%1</span> / %2").arg(getTimeStr(pos)).arg(getTimeStr(totalTime))); //更新歌詞顯示getTimeStr(pos) if (lrc->empty()) return; int key = pos / 1000; QMap<int, QString>::iterator it; if (lrc->contains(key)) { curLrc = lrc->value(key); it = lrc->find(key); if (it++ != lrc->end()) { nextLrcStr = it.value(); } } curLrc = curLrc.trimmed(); curLrc.truncate(15); if (curLrc.length() > 15) curLrc += "..."; nextLrcStr = nextLrcStr.trimmed(); nextLrcStr.truncate(15); if(nextLrcStr.length() > 15) nextLrcStr += "..."; currentLRC->setText("<center>" + curLrc +"</center>"); nextLRC->setText("<center>" + nextLrcStr +"</center>"); //cout << pos << curLrc;}//初始化歌詞void MusicPlayer::initLrc(){ if (lrc != 0) lrc->clear(); if (list == 0) return; curLrc = ""; nextLrcStr = ""; //思路,用一個map儲存10-》string的格式,然後時間到後載入,等待下一個時間 if (list->isEmpty()) return ; if (playerList == 0) return; QString fileNames = list->at(playerList->currentIndex()); QString lrcNames = fileNames; int n = lrcNames.lastIndexOf('.'); lrcNames.replace(n,lrcNames.length() - n,".lrc"); QFile file(lrcNames); QString line; if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { QTextStream stream(&file); while(!stream.atEnd()) { line = stream.readLine(); int num = line.count('['); int last = line.lastIndexOf(']'); QString str = line.right(line.length() - last -1); int begin = 0; while(num-- >0) { QString strs = line.mid(begin,10); begin += 10; strs.replace("[",""); strs.replace("]",""); int s = getSeconds(strs); if (s > 0) { lrc->insert(s,str.trimmed()); //cout << s << "=" << lrc->value(s); } } } }}void MusicPlayer::setPosition(int pos){ currentPos = pos;}void MusicPlayer::setPosition(){ player->setPosition(currentPos);}//play or pausevoid MusicPlayer::playOrPause(){ QPixmap img(("images/play.png")); if (!isPlaying) { isPlaying = true; player->play(); img.load("images/pause.png"); } else { isPlaying = false; player->pause(); img.load("images/play.png"); } playOrPauseLabel->setPixmap(img.scaled(60,60));}//時間字串00:00:00得到毫秒/秒,依賴作業系統qint32 MusicPlayer::getSeconds(QString &timeStr){ QStringList strs = timeStr.split(":"); QString s; if (strs.size() > 0) { int m = strs.at(0).toDouble(); int s = strs.at(1).toDouble(); //cout << "m" << m; //cout << "s" << s; return m * 60 + s; } return 0;}//從時,分,秒擷取總數秒qint32 MusicPlayer::getSeconds(qint32 seconds_, qint32 minutes_, qint32 hours_){ return seconds_ + minutes_ * 60 + hours_ * 3600;}//從duuation擷取字串QString MusicPlayer::getTimeStr(qint32 seconds_){ seconds_ /= 1000; qint32 minutes = seconds_ % 3600 / 60; qint32 seconds = seconds_ % 3600 % 60; minutes = minutes > 99 ? 99 : minutes + 100; seconds = seconds + 100; return QString::number(minutes).right(2).append(":").append(QString::number(seconds).right(2));}//改變時間提示//void MusicPlayer::changeTime(qint64 time)//{// timeLabel->setText(tr("T: <span style='color:Coral'>%1</span> / %2").arg(getTimeStr(time/1000)).arg(getTimeStr(totalTime)));//}//最小void MusicPlayer::setMin(){ if (!this->isMinimized()) { this->showMinimized(); }}//改變音量提示void MusicPlayer::changeVol(int vol){ volLabel->setText(tr("V:%1%").arg(QString::number(vol))); player->setVolume(vol);}//表單透明程度void MusicPlayer::paintEvent(QPaintEvent *event){ QPainter painter(this); painter.fillRect(this->rect(), QColor(100, 100, 100, 255)); //QColor最後一個參數80代表背景的透明度}//圓角表單void MusicPlayer::setRounded(bool b){ if (!bmp) { delete bmp; bmp = 0L; } if (!p) { delete p; p = 0L; } bmp = new QBitmap(this->size()); bmp->fill(); //fills the pixmap with white (default value) color p = new QPainter(bmp); p->setPen(Qt::NoPen); p->setBrush(Qt::black); if (b) p->drawRoundedRect(bmp->rect(),15,15); else p->drawRoundedRect(bmp->rect(),0,0); setMask(*bmp);//設定表單遮罩}//移動表單相關void MusicPlayer::mousePressEvent(QMouseEvent *event){ if (event->button() == Qt::LeftButton) { isMouseDown = true; oldLocation = event->globalPos() - this->pos(); } event->ignore();}//移動表單相關void MusicPlayer::mouseMoveEvent(QMouseEvent *event){ if (isMouseDown) { this->move(event->globalPos() - oldLocation); if (listUi != 0) { listUi->moves(this->sizeHint(), this->pos()); } } event->ignore();}//移動表單相關void MusicPlayer::mouseReleaseEvent(QMouseEvent *event){ isMouseDown = false; event->ignore();}
(轉載請註明作者和出處, 未經允許請勿用於商業用途)