基于QT实现Mp3播放器(代码部分)

前言

    最近有一个课程实验,利用window上的API接口实现MP3播放器。 突发奇想,在linux下用相关接口做一个MP3播放器。最先的打算是完全使用纯C写的,但后来感觉编写调试实在费劲。于是就使用了QT这个IDE工具,还可以编写个图形界面的。这篇博客主要贴代码,理论部分,请参见我的另一篇博客(基于QT实现Mp3播放器(理论部分))
    来,小二,上个图(注重逻辑,界面并没有认真规划,⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄)。
简易Mp3播放器

实现代码

playerprocess.cpp

#include "playerprocess.h"
#include

PlayerProcess::PlayerProcess(QObject *parent) : QObject(parent)
{
    process = NULL;
}




//播放Mp3文件
void PlayerProcess::play(QString mp3_file)
{
    if(mp3_file.isEmpty() == false)
    {
        QString play_tool = "mplayer";      //利用mplayer工具进行播放
        QStringList argus;

        process = new QProcess();   //每次新生成一个播放进程

        //以下是播放时的参数
        argus<<"-slave";
        argus<<"-quiet";
        argus<<mp3_file;

        //开始播放
        process->start(play_tool,argus);

        if(process->waitForStarted(5000) == false)       //等待播放进程开始
            qDebug()<<"fail to pause or replay the player";
    }
    else
        qDebug()<<"file name is empty!!!";

}
//暂停
void PlayerProcess::Pause()
{
    process->write("pause\n");      //利用mplayer提供的借口,向进程写入参数
}
//重新开始
void PlayerProcess::Rebegin()
{
    process->write("pause\n");   //利用mplayer提供的借口,向进程写入参数
}


//加音量:
void PlayerProcess::Up(int volume)
{

    QString cmd = "volume " + QString::number(volume)+" 2 \n";  //利用mplayer提供的借口,向进程写入参数
    process->write(cmd.toUtf8());
}

//减音量
void PlayerProcess::Down(int volume)
{

    QString cmd = "volume " + QString::number(volume)+" 2 \n";  //利用mplayer提供的借口,向进程写入参数
    process->write(cmd.toUtf8());
}


//结束当前播放进程
void PlayerProcess::End()
{
    if(process != NULL)      //判断是否是自动播放完毕停止,还是手动更换曲目停止
    {
        QStringList args;

        process->kill();             //kill 当前进程
        if(process->waitForFinished(5000) == false)           //等待进程结束
        {
            qDebug()<<"fail to kill the last song";
        }
        else
        {
            delete process;
            qDebug()<<"kill the last song";
        }

    }

}

//获取播放进程
QProcess* PlayerProcess::GetProcess()
{
    return process;
}

//设置播放进程
void PlayerProcess::SetProcess(QProcess * process)
{
    this->process = process;
}

player.cpp

#include "player.h"

#include 

Player::Player(QObject *parent) : QObject(parent)
{
    volume = 50;        //初始化音量为50.音量范围为0-100

    status = Player::InitStatus ;         //初始化状态

    cur_song = -2;      //init status
}

PlayerProcess* Player::GetPlaPro()
{
    return &playerprocess;
}

//返回当前播放器状态
Player::PlayStatus Player::GetPlaySta()
{
    return status;
}


//判断一个状态是否正常定义(仅限枚举变量底层用连续int实现)
bool Player::IsIncInPlaySta(PlayStatus sta)
{
    if(sta >= Player::InitStatus && sta<= Player::PauseStatus )
        return true;
    else
        return false;
}

//设置播放器状态
void Player::SetPlaySta(PlayStatus sta)
{
    if(IsIncInPlaySta(sta))
        status = sta;
    else
        qDebug()<<"player status is invalid";
}

//设置当前歌曲
void Player::SetCurSong(int index)
{
    if(index >= -1 && index <= song_list.size())        //-1代表下一次播放从最后一首开始。song_lise.size()代表下一次播放从头开始
        cur_song = index;
    else
        qDebug()<<"player index is invalid";
}

//获得播放器歌曲
int Player::GetCurSong()
{
    return cur_song;
}


//设置歌曲列表
void Player::SetSongList(QStringList list)
{
    if(list.empty() == false)
        song_list = list;
}

//添加歌曲到列表
void Player::AddSongToList(QStringList add_songs)
{
    if(add_songs.empty() == false)
        song_list.append(add_songs);
}

//获取歌曲列表
QStringList Player::GetSongList()
{
    return song_list;
}

//删除歌曲
void Player::DelSong(int index)
{
    if(index >= 0 && index <= song_list.size()-1)
    {
        song_list.removeAt(cur_song);
    }
}

//删除当前歌曲
void Player::DelCurSong()
{
    DelSong(cur_song);
}

//加音量
void Player::Up()
{
    if(volume < 100)
    {
        volume+=10;
        playerprocess.Up(volume);
    }

}
//减音量
void Player::Down()
{
    if(volume > 0)
    {
        volume-=10;
        playerprocess.Down(volume);
    }
}


//重新开始一个播放
void Player::NewPlay()
{
    if(song_list.size() == 0)        //若歌曲列表为空
    {
        qDebug()<<"song list is empty";
        return ;
    }
    else
    {
        if(cur_song == -1)       //若是第一首(0开始)以前的歌曲,就循环到歌曲列表的最后一首
            cur_song = song_list.size()-1;
        else if(cur_song == -2 || cur_song == song_list.size())      //若是超过最后一首,则回到第一首(0开始)
            cur_song = 0;

    }

    QString play_song = song_list.at(cur_song);   //获得歌曲列表内容

    playerprocess.play(play_song);         //播放


}

//播放歌曲
void Player::Play()
{
   if(status == Player::InitStatus)      //初始状态
   {
        NewPlay();          //一个新的播放任务开始
        status = Player::RunningStatus;  //设置为运行状态
   }
   else if(status == Player::RunningStatus)      //若是运行状态
   {
          playerprocess.Pause();           //暂停
          status = Player::PauseStatus;  //设置为运行状态
   }
   else
   {
       playerprocess.Rebegin();       //重新开始
       status = Player::RunningStatus; //设置为运行状态

   }

}

//下一曲
void Player::Next()
{
    if(cur_song == -2)      //init status
        cur_song = 0;
    else
        ++cur_song;

}

// 上一曲
void Player::Pre()
{
    if(cur_song == -2)      //init status
        cur_song = 0;
    else
        --cur_song;

}

//kill当前播放进程
void Player::End()
{
    playerprocess.End();
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"

#include
#include


Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    InitWindow();       //初始化窗口
}

Widget::~Widget()
{
    delete ui;
}

//初始化窗口:大小、颜色、背景等
void Widget::InitWindow()
{
    setWindowTitle("EasyMp3Player");

    setFixedSize(this->width(),this->height());

    //设置背景
    QPalette PAllbackground = this->palette();
    QImage ImgAllbackground(":/back.png");
    QImage fitimgpic=ImgAllbackground.scaled(this->width(),this->height(), Qt::IgnoreAspectRatio);
    PAllbackground.setBrush(QPalette::Window, QBrush(fitimgpic));
    this->setPalette(PAllbackground);


    QFont item_font;
    item_font.setPixelSize(50);
    item_font.setBold(true);

    ui->listWidget->setStyleSheet("background-color:transparent; QListWidget::item(color:black)");
}

//高亮选中的歌曲栏目
void Widget::HighLigCurSong()
{
    int cur_song = player.GetCurSong() ;
    QStringList song_list = player.GetSongList();

    if(cur_song>=0 && cur_song <= song_list.size()-1)
    {
        QListWidgetItem * tmp =  ui->listWidget->item(cur_song);
        tmp->setBackgroundColor(QColor("orange"));        //当前播放歌曲高亮
    }

}

//显示歌曲列表
void Widget::ShowSongList()
{
    ui->listWidget->clear();

    QStringList songs;
    QStringList song_list = player.GetSongList();
    foreach (QString song_dir, song_list)
    {
        songs.append(QFileInfo(song_dir).fileName());
    }

    ui->listWidget->addItems(songs);

    HighLigCurSong();   //高亮

}

//点击播放按钮
void Widget::on_pushButton_play_clicked()
{
    Player::PlayStatus status = player.GetPlaySta();

    player.Play();  //播放歌曲
    if(status == Player::InitStatus)
        ConnectNewProcess();        //连接新的player进程到自动播放结束槽

    //关联每个播放进程结束信号和槽
   ShowSongList();          //在QListWidget中显示歌曲列表

}

//下一曲
void Widget::on_pushButton_next_clicked()
{

    Player::PlayStatus status = player.GetPlaySta();

    if(status == Player::RunningStatus)
        player.End();

    player.Next();       //下一曲

    player.SetPlaySta(Player::InitStatus);  //回到初始状态

    on_pushButton_play_clicked();

}

//上一曲
void Widget::on_pushButton_pre_clicked()
{
    Player::PlayStatus status = player.GetPlaySta();

    if(status == Player::RunningStatus)     //是否是从运行状态点击上一曲
        player.End();

    player.SetPlaySta(Player::InitStatus);      //回到初始状态
    player.Pre();        //上一曲
    on_pushButton_play_clicked();

}

//添加歌曲到播放列表
void Widget::on_pushButton_Add_clicked()
{
    QStringList file_names = QFileDialog::getOpenFileNames(this,tr("choose a song"),".","music(*.mp3)");

    player.AddSongToList(file_names);
    ShowSongList();         //show song list
}

//删除当前歌曲
void Widget::on_pushButton_del_clicked()
{

    player.DelCurSong();        //删除当前歌曲

    ShowSongList();
    player.End();       //结束当前播放歌曲

    player.SetPlaySta(Player::InitStatus);
    on_pushButton_play_clicked();

}


//加音量
void Widget::on_pushButton_up_clicked()
{
    player.Up();
}

//减音量
void Widget::on_pushButton_down_clicked()
{
    player.Down();
}

 //连接新的player进程到自动播放结束槽
bool Widget::ConnectNewProcess()
{
    QProcess * tmp = player.GetPlaPro()->GetProcess();
    if(tmp != NULL)
    {
        connect(tmp ,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(PlayEnd(int,QProcess::ExitStatus)));
        return true;
    }
    else
    {
        qDebug()<<"connect new player process failed";
        return false;
    }
}

//一首歌曲自动播放结束
void Widget::PlayEnd(int code, QProcess::ExitStatus exit_status)
{
    if(exit_status == QProcess::NormalExit)     //正常退出(注意:切换下一曲、上一曲为播放进程为非正常退出)
    {

        player.GetPlaPro()->SetProcess(NULL);   //设置为空
        on_pushButton_next_clicked();       //下一曲
        ShowSongList();     //显示列表
    }

}

//程序退出,把所有的播放进程删除
void Widget::closeEvent(QCloseEvent *event)
{
    player.End();
}

//退出
void Widget::on_pushButton_Quit_clicked()
{
    close();
}

   具体的代码都比较简单,注释也相对详细。这里只说一个点(不关心的可以略过)。如下
当前歌曲播放完毕之后需要切换下一首,因为是每次使用QProcess新进程播放音乐,所以主进程和播放的进程相对独立,这样的话就必须在新建QProcess进程时connect播放进程的退出状态到具体的槽(在这个槽中进行新建下一个播放进程,否则达不到自动切换的目的,同时也为了更改(高亮)下一首歌曲)。
问题是如果使用上述分层的设计按理说,这部分connect的代码应该放在player这层中,但是player是做为一个widget的一个对象,这样的话,就没法调用包括ShowSongList()的槽。 这个问题想了很久,尝试了很多方法,还是不太满意。最后只能把connect连接放在widget中实现了。

后言

具体的工程代码已经打包了,有需要的请到对应的资源页进行下载。

你可能感兴趣的:(项目实践)