• 1083阅读
  • 0回复

linux的mplayer的Qt界面化音乐播放器 [复制链接]

上一主题 下一主题
离线tech_cat
 

只看楼主 倒序阅读 楼主  发表于: 2023-09-17
各位看官,本人 不吃鱼刺的科技猫(tech_cat)熬个夜把之前的写的小项目拿了出来复习了一番,之前花了一段时间写了一个基于linuxmplayer的Qt界面化音乐播放器。就在QT社区共享一下,与诸位大佬讨论一下技术,在这也感谢 QTCN 平台
文中哪里写的不对和不好,尽管赐教, tech_act 大恩不言谢
本次调试并解决大部分bug:
  1. 歌词和歌曲不同步
  2. 点击pause 按钮再点击下一首歌曲出现程序异常
  3. 在歌曲暂时的时候拖动音量条,歌曲时间进度不动
  4. 音量一开始为0,但是也有声音播放
  5. 按下pause按钮定时器不停止
  6. 等等诸多问题
下面为大家简单介绍一个所用原理和主要代码也给大家附上(本人没想到字数才5000,只能附上这些代码了,有需要的话可以交流)。
首先,本次的基本播放器小项目所用详细原理如下:
  1. 在QT 中创建父子进程,子进程 execlp 调用 linux 下的 mplayer 可执行程序,父进程通过创建的 有名管道用于向 mplayer   的slave模式(注:slave 模式用于用户开发mplayer模式)下写入命令,使播放器实现想要的功能,如seek  value 、 get_time_length等等。
  2. 通过无名管道来获取子进程 mplayer 在 stdout 流中的数据情况,以便调试相应功能。
  3. 一开始本来想直接用文件 IO 来遍历文件获取歌单,想了一下还是用 标准 IO 兼容一些,文件不大,速率影响也不大;获取的歌单用 vector 进行动态存储,再通过 Qpushbutton 来触发信号 来连接槽函数,槽函数中用来 vector 的 iterator 来获取上下歌曲名; (注:若歌曲少的话,建议可以使用数组来存储,毕竟数组访问元素速度最快嘛)
  4. 再通过歌曲信息来进行对歌词解析存储,本次采用  vector 存储 class 类型,class 类中用有歌曲时间和歌词两个成员。本想用 链表进行存储的 但感觉会代码很乱, 各位看官怎么看?
  5. 最后就是一些小细节问题了,歌词显示用了Qlistwdight 控件等等。
然后呢,就是项目功能:

  1. 可以动态显示当前歌曲的歌名、作曲者、专辑歌词信息
  2. 歌词显示可以随进度变化而变化,使所唱的歌词实时显示
  3. 可以点击上一曲和下一曲以及暂停
  4. 拖动音量可以显示音量数值
  5. 点击文件夹图标可以显示歌单和关闭歌单
  6. 可以拖动时间进度条,随之歌曲和歌词同步等

下期说一下 用户界面登录 注册的全面代码!


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

    unlink("./myfifo");
    pipe(pipe_fd);
    int ret = mkfifo("./myfifo", O_CREAT | 0666);
    if( ret < 0)
    {
        perror("mkfifo error:");
    }

    fd = open ("./myfifo", O_RDWR);
    if( fd < 0)
    {
        perror("open rror");
    }

    s_pid = fork();
    if( s_pid==0 )
    {
        dup2(pipe_fd[1],1);
        execlp("mplayer","mplayer","-slave", "-idle", "-quiet", "-input","file=./myfifo",\
               "/home/edu/QT/project/music_1/build-music_1-Desktop_Qt_5_4_2_GCC_64bit-Debug/song_new/StopLove.mp3",NULL);
    }else{
        sleep(1);
    }
    get_volume();
    ui->volume->setRange(0,100);
    get_play_list();
    timer = new  QTimer(this);
    timer->start(1000);
    memset(buff_clr,0,sizeof(buff_clr));
    strcpy(buff_clr, "/home/edu/QT/project/music_1/build-music_1-Desktop_Qt_5_4_2_GCC_64bit-Debug/song_new/StopLove.mp3");
    lrc = new Lrc(buff_clr);
    set_lrccinfo(lrc);
    ui->Pos->setMinimum(0);
    ui->Pos->setMaximum(lrc->lrcVector.back()->lrc_time);
    ui->listWidget->clear();
    ui->song_list->hide();

        connect(timer,SIGNAL(timeout()), this, SLOT(mytimer()));
    //    connect(this,&Widget::time_end, this, &Widget::on_N_clicked);
        connect(this,SIGNAL(time_end()),this,SLOT(on_N_clicked()));
        connect(ui->volume,SIGNAL(sliderPressed()), this,SLOT(trans_signal()));
        connect(this,SIGNAL(volume_change_pause()), this,SLOT(on_P_clicked()));
        connect(ui->Pos,SIGNAL(valueChanged(int)),this,SLOT(sliderValueChangedSlot(int)));
}

Widget::~Widget()
{
    kill(s_pid,9);
    delete ui;
}



    if( time_pos == (lrc->lrcVector.back()->lrc_time ))
    {
        emit time_end();

    }

}



//***************** get_timelength  ********************
void Widget::get_time_length(void)
{
   int  ret = write(fd, "get_time_length\n",strlen("get_time_length\n"));
   if(ret <  0)
   {
       qDebug()<<"write  erro"<<endl;

   }
   int ret2 = read(pipe_fd[0], good_buff,sizeof(good_buff));
   if(ret2 < 0)
   {
       perror("read error");
   }
    qDebug()<<good_buff;
   int time_length = 0;
   sscanf(good_buff, "ANS_LENGTH=%d",&time_length);
   qDebug()<< " --------" << time_length;

   int  min = 0, sec = 0;
   min = time_length/60;
   sec = time_length%60;
   char mytime[6]={'0'};
   ui->current_time->setText(mytime);
   sprintf(mytime,"%02d:%02d",min,sec);
   qDebug()<< mytime;
   ui->Tlength->setText(mytime);
   ui->Pos->setMaximum(time_length);

   memset(good_buff,0,sizeof(good_buff));

}

//pause
void Widget::on_P_clicked()
{
        write(fd, "pause\n", strlen("pause\n"));

        if( !time_flag )
        {

            ui->P->setIcon(QIcon(":/image/button_style/front1.png"));
            time_flag = 1;
            timer->stop();
        }else{
            ui->P->setIcon(QIcon(":/image/button_style/pause1.png"));
            time_flag = 0;
           timer->start();
        }
}

//former song
void Widget::on_F_clicked()
{

     memset(bad_buff,0,sizeof(bad_buff));
    if(currentSong == playlist.begin())
    {
        currentSong = playlist.end();  //the point next ,so error
        qDebug()<< "-------end of song --------"<< endl;
    }
    currentSong--;

    std::string tempStr = (*currentSong).toStdString();
    const char* cStr = tempStr.c_str();
    char arr[128]={};
    sprintf(arr,"loadfile /home/edu/QT/project/music_1/build-music_1-Desktop_Qt_5_4_2_GCC_64bit-Debug/song_new/%s\n",cStr);

//************************************************
    memset(buff_clr,0,sizeof(buff_clr));
    sprintf(buff_clr, "/home/edu/QT/project/music_1/build-music_1-Desktop_Qt_5_4_2_GCC_64bit-Debug/song_new/%s",cStr);
    lrc = new Lrc(buff_clr);
    set_lrccinfo(lrc);
    ui->Pos->setMinimum(0);
    ui->Pos->setMaximum(lrc->lrcVector.back()->lrc_time);

    if( lrc->lrc_error_flag == -1)
    {
        QMessageBox::information(this,"worning","lrc is not exsits");
    }
    time_pos = -1 ;
    time_flag = 0;
    vector_pos = -1;
    timer->start();
//**************************************************

    qDebug() << "Loading file: " << arr;
    write(fd, arr, strlen(arr));
}

//next song
void Widget::on_N_clicked()
{
    qDebug()<<"time______end---------";
    this->timer->stop();
    currentSong++;
    if(currentSong == playlist.end())
    {
        currentSong = playlist.begin();  //the point next ,so error
        qDebug()<< "-------begin of song --------"<< endl;
    }
    std::string tempStr = (*currentSong).toStdString();
    const char* cStr = tempStr.c_str();
    char arr[128]={};
    sprintf(arr,"loadfile /home/edu/QT/project/music_1/build-music_1-Desktop_Qt_5_4_2_GCC_64bit-Debug/song_new/%s\n",cStr);

//************************************************
    memset(buff_clr,0,sizeof(buff_clr));
    sprintf(buff_clr, "/home/edu/QT/project/music_1/build-music_1-Desktop_Qt_5_4_2_GCC_64bit-Debug/song_new/%s",cStr);
    lrc = new Lrc(buff_clr);
    set_lrccinfo(lrc);
    ui->Pos->setMinimum(0);
    ui->Pos->setMaximum(lrc->lrcVector.back()->lrc_time);

    if( lrc->lrc_error_flag == -1)
    {
        QMessageBox::information(this,"worning","lrc is not exsits");
    }

//**************************************************

    qDebug() << "Loading file: " << arr;
    write(fd, arr, strlen(arr));

    qDebug()<< "from---------";
     timer->start();
     qDebug()<<"latter-------";
     time_pos = -1;
     time_flag = 0;
     vector_pos=-1;

}

//get song-list
void Widget::get_play_list(void)
{
    char *path_song = "/home/edu/QT/project/music_1/build-music_1-Desktop_Qt_5_4_2_GCC_64bit-Debug/song_new";
    DIR *dir = opendir(path_song);
    struct dirent *p = NULL;
    if( dir )
    {
        while( p = readdir(dir) )
        {
            if( strcasecmp(p->d_name + strlen(p->d_name)-4, ".mp3") == 0)
            {
                playlist.push_back(p->d_name);
            }
        }
    }else {
             perror(" dir NULL :");
    }

    //show songs
    ui->song_list->setPlainText("歌单:");
    for(const QString &song :playlist)
    {
         qDebug("%s",qPrintable(song)) ;
         ui->song_list->append(song);
         song_num++;
    }

    qDebug()<< song_num << endl;
    currentSong = playlist.begin();

}



//****************** get_volume **************************
void Widget::get_volume(void)
{
   read(pipe_fd[0],bad_buff,sizeof(bad_buff));
   memset(bad_buff,0,sizeof(bad_buff));

   int  ret = write(fd, "get_property volume\n",strlen("get_property volume\n"));
   if(ret <  0)
   {
       qDebug()<<"write  erro"<<endl;

   }
   int ret2 = read(pipe_fd[0], good_buff,sizeof(good_buff));
   if(ret2 < 0)
   {
       perror("read error");
   }
    qDebug()<<"@@@@@@@@@@@@@@@@@@@@@"<<good_buff<<endl;
   int G_volume = 0;
   sscanf(good_buff, "ANS_volume=%d",&G_volume);
   memset(good_buff,0,sizeof(good_buff));
   qDebug()<< " --------" << G_volume;
   ui->volume->setValue(G_volume+1);
   ui->volume_1->setValue(G_volume+1);
}


//show  volume
void Widget::on_volume_1_valueChanged(int arg1)
{
     ui->volume->setValue(arg1);
}


//adapt  volume
void Widget::on_volume_valueChanged(int value)
{
    ui->volume_1->setValue(value);
    sprintf(buff,"volume %d 1\n",value);
    qDebug()<<"buff:"<<buff<<endl;
     write(fd, buff, strlen(buff));
     memset(buff, 0, sizeof(buff));
}


//adapt pos
void Widget::sliderValueChangedSlot(int value)
{
    time_flag = 0;
    usleep(10);
    this->timer->stop();
    if(value != time_pos)
    {
       char str[128] = {};
       double precent  = std::round((double)value /lrc->lrcVector.back()->lrc_time *100 );
       sprintf(str, "seek %lf 1\n", precent);
       qDebug()<< str;
       //write(fd, "seek %d  2\n", value - time_pos);
       if(write(fd, (char *)str, strlen(str)) < 0)
       {
           printf("write error");
           return ;
        }
//        timer->start();
    }

    //设置时间标签
        int   min = 0, sec = 0;
        min = value /60;
        sec = value % 60;
        char mytime[6] = "";
        sprintf(mytime,"%02d:%02d",min,sec);
        ui->current_time->setText(mytime);

//      //更改歌词位置
        time_pos = value;
        if(time_pos != lrc->lrcVector[vector_pos]->lrc_time)
        {
            if(time_pos < lrc->lrcVector[vector_pos]->lrc_time)
            {
              while (vector_pos > 0 && time_pos < lrc->lrcVector[vector_pos]->lrc_time)
              {
                  vector_pos--;
              }
            } else {
              while (vector_pos < lrc->lrcVector.size() - 1 && time_pos > lrc->lrcVector[vector_pos]->lrc_time) {
                  vector_pos++;
              }


//change pause
void Widget::trans_signal()
{

    if(time_flag ==1)
    {
        emit volume_change_pause();
    }

}

void Widget::on_sing_list_clicked()
{
    if(!flag_list)
    {
        flag_list = 1;
        ui->song_list->show();
    }else{
        flag_list = 0;
        ui->song_list->hide();
    }

}
4条评分好评度+1贡献值+1金钱+10威望+1
20091001753 好评度 +1 - 2023-09-19
20091001753 贡献值 +1 - 2023-09-19
20091001753 威望 +1 - 2023-09-19
20091001753 金钱 +10 - 2023-09-19
快速回复
限100 字节
 
上一个 下一个