音乐播放器
首先,这个音乐播放器支持大多数音频文件的播放,在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已经对应相应的歌曲)播放双击点中音乐 }
https://files.cnblogs.com/li-zi/%E9%9F%B3%E4%B9%90%E6%92%AD%E6%94%BE%E5%99%A8.rar 音乐播放器源码