首先,這個音樂播放器支持大多數音頻文件的播放,在linux下開發的,用QT做的界面,后台音頻解碼器用的是madplay.
下載好madplay在linux下解壓安裝,扔進/usr/bin目錄。 也就相當於一個命令。
之后在做好界面編寫,當然,界面不是直接用圖形ui來實現,而是通過控件布局來實現,都是代碼一步一步敲出來的。
之后在交叉編譯移植到ARM板里。 當然,移植進去之后還需要配置相應環境變量。 不過,這也需要一個支持界面的文件系統,
先是做了個yaffs文件系統,之后改進成qt文件系統,這其中用到的BusyBox工具在此就不在贅述。 那OK,一切准備好,程序也移植好,
環境變量也配置好, 那么現在我們來看看MP3的真面目:
第一個選歌曲,第2個暫停,第3個下一曲,第4個播放,第5個上一曲,第6個停止,隱藏的第7個歌曲單。
選擇歌曲:
播放效果:
那我們可以看見總時間,進度條,以及實時時間和進度條同步,可以拖拽進度條,時間也會同步。 還可以改變音量。
選取多首歌曲:
那我們可以看到播放列表里面選中了多首歌曲,那么接下來就可以進行上下首切換了。
部分代碼:
#include "musicplayer.h" /*窗口界面創建模塊(構造函數)*/ MusicPlayer::MusicPlayer(QWidget *parent) : QMainWindow(parent) { i = 0; Com1 = 1; list_flag = 0; Timer_flag = 0; sumnumber = 0; ft = ::open("/dev/mixer", O_RDWR); //this->sizeHint(); this->resize(550,320); setWindowTitle(trUtf8("MP3音樂播放器")); QPixmap pixmap(":/images/3.jpg"); QPalette palette; palette.setBrush(backgroundRole(), QBrush(pixmap)); setPalette(palette); /*build toolBar , setToolButtonStyle add put in "this"*/ toolBar = new QToolBar(this); toolBar->setWindowTitle("Actions"); toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->addToolBar(toolBar); /*build a widget put int centralwidget of this*/ widget = new QWidget; setCentralWidget(widget); /*make a layout put all widget*/ mainLayout = new QHBoxLayout(widget); /*some Action information*/ open = new QAction(trUtf8("打開"),this); open->setIcon(QIcon(":/images/dir.png")); open->setShortcut(QKeySequence::Open); connect(open,SIGNAL(triggered()),this,SLOT(slotopen())); toolBar->addAction(open); pause = new QAction(trUtf8("暫停"),this); pause->setIcon(QIcon(":/images/pause.png")); connect(pause,SIGNAL(triggered()),this,SLOT(slotpause())); toolBar->addAction(pause); next = new QAction(trUtf8("下一曲"),this); next->setIcon(QIcon(":/images/next.jpg")); toolBar->addAction(next); connect(next,SIGNAL(triggered()),this,SLOT(slotnext())); play = new QAction(trUtf8("播放"),this); play->setIcon(QIcon(":/images/play.png")); connect(play,SIGNAL(triggered()),this,SLOT(slotplay())); toolBar->addAction(play); last = new QAction(trUtf8("上一曲"),this); last->setIcon(QIcon(":/images/up.jpg")); connect(last,SIGNAL(triggered()),this,SLOT(slotlast())); toolBar->addAction(last); stop = new QAction(trUtf8("停止"),this); stop->setIcon(QIcon(":/images/stop.png")); connect(stop,SIGNAL(triggered()),this,SLOT(slotstop())); toolBar->addAction(stop); musiclist = new QAction(trUtf8("播放器"),this); musiclist->setIcon(QIcon(":/images/stop.png")); connect(musiclist,SIGNAL(triggered()),this,SLOT(slotlisting())); toolBar->addAction(musiclist); /*build other widget */ nameLabel = new QLabel; nameLabel->setText(trUtf8("歌曲名")); authorLabel = new QLabel; authorLabel->setText(trUtf8("作者")); starttime = new QTimeEdit; starttime->setDisplayFormat("hh:mm:ss"); starttime->setDisabled(true); overtime = new QTimeEdit; overtime->setDisplayFormat("hh:mm:ss"); overtime->setDisabled(true); textedit = new QTextEdit(); horizontalprogress = new QSlider(Qt::Horizontal); verticalvolume = new QSlider(Qt::Vertical); verticalvolume->setTickPosition(QSlider::TicksBothSides); verticalvolume->setMaximumWidth(20); verticalvolume->setRange(40,120); verticalvolume->setValue(70); connect(verticalvolume,SIGNAL(valueChanged(int)),this,SLOT(soltvolume())); QHBoxLayout *leftlayout= new QHBoxLayout(); leftlayout->setSpacing(5); leftlayout->addWidget(nameLabel); leftlayout->addWidget(authorLabel); leftlayout->addWidget(starttime); leftlayout->addWidget(overtime); QVBoxLayout *mainleftlayout = new QVBoxLayout(); mainleftlayout->setSpacing(30); mainleftlayout->addLayout(leftlayout); mainleftlayout->addWidget(horizontalprogress); mainleftlayout->addWidget(textedit); mainLayout->setMargin(35); mainLayout->setSpacing(40); mainLayout->addLayout(mainleftlayout); mainLayout->addWidget(verticalvolume); } MusicPlayer::~MusicPlayer() { fn1.clear(); system("killall -9 madplay"); } /*基本按鍵功能模塊*/ /*打開功能實現*/ void MusicPlayer::slotopen() { fn2 = QFileDialog::getOpenFileNames(this, tr("open one or more file"), tr("/mnt/hgfs/share"), tr("mp3files(*.mp3);;all files(*)")); /* QString directory = QFileDialog::getExistingDirectory(this, "fine a directory", "/mnt/hgfs/share", QFileDialog::ShowDirsOnly); QDir dir(directory); QStringList type; type<<"*mp3"<<"*.txt"; fn1 = dir.entryList(type,QDir::Files,QDir::Name); */ fn1 = fn1.operator+(fn2); slotplay(); } /*暫停功能實現*/ void MusicPlayer::slotpause() { if(1 == Com1) { timer->stop(); system("killall -STOP madplay &"); Com1 = 0; } else { timer->start(1000); system("killall -CONT madplay &"); Com1 = 1; } } /*上一曲功能實現*/ void MusicPlayer::slotlast() { if(0 != fn1.count()) { if(0 == i) { QMessageBox::information(this,"Hi,man.",tr("it is first music..")); } else { i--; timer->stop(); horizontalprogress->setValue(0); addtime = inittime.addSecs(0); starttime->setTime(addtime); slotplay(); } } } /*播放功能實現*/ void MusicPlayer::slotplay() { if(fn1.count() != 0) { QString commend = "madplay -m -v"; commend.append(tr(" ")); commend.append(fn1.at(i)); commend.append(tr(" ")); commend.append(tr("&")); openfile = commend.toLatin1().data(); getfilename = fn1.at(i); filename = getfilename.fileName(); nameLabel->setText(filename); system("killall -9 madplay"); system(openfile); information(); someset(); } } /*下一曲功能實現*/ void MusicPlayer::slotnext() { if(i == (fn1.count()-1)) { QMessageBox::information(this,"Hi,man.",tr("it is last music..")); } else if(i < (fn1.count()-1)) { i++; timer->stop(); horizontalprogress->setValue(0); addtime = inittime.addSecs(0); starttime->setTime(addtime); slotplay(); } } /*停止功能實現*/ void MusicPlayer::slotstop() { timer->stop(); system("killall -9 madplay"); } /*音量大小功能實現*/ void MusicPlayer::soltvolume() { /*put verticalvolume volume to dev*/ int usr_volume; usr_volume = verticalvolume->value(); ioctl(ft,MIXER_WRITE(0),&usr_volume); } /*獲取時間模塊*/ /*獲取信息*/ void MusicPlayer::information() { if(0 != fn1.count()) { position = 0; filename1 = (fn1.at(i)).toLatin1().data(); if(NULL == (fp = fopen(filename1,"rb"))) { printf("error : can't open file ."); getchar(); exit(1); } fineframe(); //找幀頭 obtaim_info(); //獲取比特率和采樣頻率 readinfo(); //讀數據 } } /*找幀頭*/ void MusicPlayer::fineframe() { fseek(fp,position,SEEK_SET); //初始化中position為0 fread(Mp3_ID3V1.Header,3,1,fp); //從fp中讀三個字節到Mp3_ID3V1.Header if((Mp3_ID3V1.Header[0]=='I')&(Mp3_ID3V1.Header[1]=='D') &(Mp3_ID3V1.Header[2]==0x33)) {//判斷 //QMessageBox::information(this,"Hi,man.",tr("it has id3v2 ..")); obtain_ID3V2size(); //獲取ID3V2的大小,獲取值為整型 str = str.number(first); position = str.toLong(); //這兩步將整型轉換成long型 fseek(fp,position,SEEK_SET); //指針從0條到position處 fread(Mp3_ID3V1.Header,3,1,fp); //從fp中讀取三個字節存到Mp3_ID3V1.Header } } /*獲取文件ID3V2大小*/ void MusicPlayer::obtain_ID3V2size() { fseek(fp,6L,SEEK_SET); //跳到指定位置 fread(Mp3_ID3V2.Size,4,1,fp); //按規格讀取數據 /*根據算法技術ID3V2的大小,復制到first中*/ first = (Mp3_ID3V2.Size[0]&0x7F)*0x200000+(Mp3_ID3V2.Size[1]&0x7F)*0x400+(Mp3_ID3V2.Size[2]&0x7F)*0x80+(Mp3_ID3V2.Size[3]&0x7F)+10; } /*根據不同類型文件來獲取文件時間*/ void MusicPlayer::readinfo() { /*跳到XING指定位置讀取數據,存到temp中*/ position = 0+4+32; fseek(fp,position,SEEK_SET); fread(temp,4,1,fp); /*跳到VBP指定位置讀取數據,存到temp1中*/ position = 0+32; fseek(fp,position,SEEK_SET); fread(temp1,4,1,fp); if((temp[0]=='X')&(temp[1]=='i')&(temp[2]=='n')&(temp[3]=='g')) {//如果獲取的是XING頭,則按規格獲取xing頭文件時間. position = (0+4+32)+8; obtain_VBRtime(); } else if((temp1[0]=='V')&(temp1[1]=='B')&(temp1[2]=='R')&(temp1[3]=='I')) {//如果獲取的是VBRI頭,則按規格獲取VBR頭文件時間. position = (0+32)+14; obtain_VBRtime(); } else {//如果都不是,那就按CBP規格來獲取CBP時間 obtain_CBPtime(); } } /*獲取比特率和采樣頻率*/ void MusicPlayer::obtaim_info() { char number = Mp3_ID3V1.Header[2]&0xf0; switch(number) { case 0x10: bitrate = 32; break; case 0x20: bitrate = 40; break; case 0x30: bitrate = 48; break; case 0x40: bitrate = 56; break; case 0x50: bitrate = 64; break; case 0x60: bitrate = 80; break; case 0x70: bitrate = 96; break; case 0x80: bitrate = 112; break; case 0x90: bitrate = 128; break; case 0xa0: bitrate = 160; break; case 0xb0: bitrate = 192; break; case 0xc0: bitrate = 224; break; case 0xd0: bitrate = 256; break; case 0xe0: bitrate = 320; break; default: bitrate = 128; } char number1 = Mp3_ID3V1.Header[2]&0x0c; switch(number1) { case 0x00: sampling = 44100; break; case 0x04: sampling = 48000; break; case 0x08: sampling = 32000; break; } } /*獲取CBP文件的時間*/ void MusicPlayer::obtain_CBPtime() { qint64 fsize; QFileInfo filesize(fn1.at(i)); fsize = filesize.size(); second = fsize*8/bitrate/1000; str1 = str1.number(second); textedit->setText(str1); displaytime(); //顯示時間 obtain_ID3V1(); //顯示ID3V1信息,可要可不要。 } /*顯示ID3V1信息*/ void MusicPlayer::obtain_ID3V1() { fseek(fp,-128L,SEEK_END); fread(Mp3_ID3V1.Header,3,1,fp); fseek(fp,-125L,SEEK_END); fread(Mp3_ID3V1.Title,30,1,fp); fseek(fp,-95L,SEEK_END); fread(Mp3_ID3V1.Artist,30,1,fp); fseek(fp,-65L,SEEK_END); fread(Mp3_ID3V1.Album,30,1,fp); fseek(fp,-35L,SEEK_END); fread(Mp3_ID3V1.Year,4,1,fp); fseek(fp,-31L,SEEK_END); fread(Mp3_ID3V1.Comment,28,1,fp); fseek(fp,-1L,SEEK_END); fread(Mp3_ID3V1.Cenre,1,1,fp); textedit->append(fn1.at(i)); str = QString(Mp3_ID3V1.Header); textedit->append(str); str = QString(Mp3_ID3V1.Title); textedit->append(str); str = QString(Mp3_ID3V1.Artist); textedit->append(str); authorLabel->setText(tr(Mp3_ID3V1.Artist)); str = QString(Mp3_ID3V1.Album); textedit->append(str); str = QString(Mp3_ID3V1.Year); textedit->append(str); str = QString(Mp3_ID3V1.Comment); textedit->append(str); str = QString(Mp3_ID3V1.Cenre); textedit->append(str); } /*獲取VBR文件的時間*/ void MusicPlayer::obtain_VBRtime() { fseek(fp,position,SEEK_SET); fread(date,4,1,fp); str = QString(date); sumnumber = str.toInt(); second = sumnumber*(1152*(1/sampling)); displaytime(); } /*顯示時間*/ void MusicPlayer::displaytime() { QTime time(0,0,0); time = time.addSecs(second); overtime->setTime(time); } /*時間、進度條同步模塊*/ void MusicPlayer::someset() { horizontalprogress->setRange(0,second); //設定水平條范圍為0到MP3總時間 horizontalprogress->setValue(0); //設置初始值為0 connect(horizontalprogress,SIGNAL(sliderMoved(int)),this,SLOT(slotchangeplay())); //當拖動水平條時,進入槽函數,跳轉到制定時間進行播放。 inittime.isValid(0,0,0); starttime->setTime(inittime); if(0 == Timer_flag) {//以時間標志位來判斷,確保定時器只創建一個,我們也只需要一個。 timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(slottime())); //如果定時器溢出,進入slottime槽函數,實現水平進度條和開始時間的同步 Timer_flag = 1; } timer->start(1000); //以一秒為大小,開始運行定時器 } void MusicPlayer::slottime() { horizontalprogress->setValue((horizontalprogress->value())+1); //水平進度條的值+1 addtime = inittime.addSecs(horizontalprogress->value()); //獲取水平進度條的值 starttime->setTime(addtime); //水平進度條的值賦給開始時間 if(second == horizontalprogress->value()) {//判斷如果水平條的值等於MP3總時間說明播放結束,做一下設置. timer->stop(); //停止定時器 horizontalprogress->setValue(0); //水平條置0 addtime = inittime.addSecs(0); //獲取QTime類對象值為0 starttime->setTime(addtime); //開始時間置0 } } void MusicPlayer::slotchangeplay() { addtime = inittime.addSecs(horizontalprogress->value()); //獲取時間進度條的值存到QTime的對象 seektime = addtime.toString(); //QTime的對象轉換成字符串 即 “12:12:12” starttime->setTime(addtime); //開始時間顯示為進度條的值 /*一下代碼實現切換到seektime所表示的時間播放*/ QString commend = "madplay -m --start="; commend.append(seektime); commend.append(" "); commend.append(fn1.at(i)); commend.append(" "); commend.append(tr("&")); textedit->append(commend); openfile = commend.toLatin1().data(); system("killall -9 madplay"); system(openfile); } /*播放列表模塊*/ void MusicPlayer::slotlisting() { if(!list_flag) {//以標志位為判斷,確保創建執行一次。 list = new listing; //創建列表對象 list_flag = 1; //將標志位置1,意味着list只創建一次。 } list->show();//顯示播放列表 connect(list->buttonAdd,SIGNAL(clicked()),this, SLOT(slotaddmusic()));//點擊添加按鈕時,進入slotaddmusic()添加音樂。 connect(list->listWidget2,SIGNAL(itemDoubleClicked(QListWidgetItem*)), this,SLOT(slotplaylistmusic()));//雙擊列表里歌曲時,進入slotplaylistmusic()實現擊中歌曲播放 } void MusicPlayer::slotaddmusic() { QFileInfo info; //存放文件路徑 slotopen(); //打開文件,獲取文件信息 for(j=0;j<fn2.count();j++) {//fn2是每一次打開選中文件的數量,即打開了多少文件,添加多少文件。 info = fn2.at(j); //將選中的歌曲路徑放到QFileInfo類中,因后面要取其文件名。 list->listWidget2->addItem(info.fileName()); //在播放列表的QlistWidget對象(列表框)中加入文件名。 } } void MusicPlayer::slotplaylistmusic() { timer->stop(); //定時器停止,切換歌曲時需要先將定時器停下。 horizontalprogress->setValue(0);//水平進度條置0 addtime = inittime.addSecs(0); //獲取QTime時間為0的對象,下一句setTime()中需要。 starttime->setTime(addtime); //將開始時間設置為0 i = list->listWidget2->row(list->listWidget2->currentItem()); //雙擊點中之后,獲取當前項,並取出其索引(0,1,2,3,4等),賦值到i中。 slotplay(); //(i已經對應相應的歌曲)播放雙擊點中音樂 }
http://files.cnblogs.com/li-zi/%E9%9F%B3%E4%B9%90%E6%92%AD%E6%94%BE%E5%99%A8.rar 音樂播放器源碼