音乐播放器

 

 

    首先,这个音乐播放器支持大多数音频文件的播放,在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     音乐播放器源码

posted @ 2012-12-01 00:03  桥段、  阅读(2049)  评论(6编辑  收藏  举报