音樂播放器


 

 

    首先,這個音樂播放器支持大多數音頻文件的播放,在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     音樂播放器源碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM