網路MP3完工

來源:互聯網
上載者:User

下載功能實現了,不過懶得多寫,乾脆用 <- 按鍵代替預設下載一首歌。

調節音量madplay做不到,需要自己開啟音效卡驅動,沒做。進度條是擺設。

完成的功能:

播放,上/下一首,雙擊歌名播放,歌詞同步顯示。

運行環境:ARM92t0 s3c2440開發板,linux無介面,qt

開發環境:qt      arm-linux-gcc

先在PC機上開發,後移殖到ARM板上。

 

將就將就吧,做的爛,也有收穫。

 

PC機上開發ARM板上效果

 

關鍵代碼(QT工程不發了,標頭檔也不發,man一下就知道的,也就看下怎麼實現):

#include "mp3.h"#include "ui_mp3.h"class mp3 *pthis;mp3::mp3(QWidget *parent) :    QWidget(parent),    ui(new Ui::mp3){    ui->setupUi(this);/************************* TO DO **************************/    this->setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint | Qt::FramelessWindowHint);    my_init();              // 自訂的一些初始化動作}mp3::~mp3(){    delete ui;}/************************************TO DO****************************//* 自訂初始化 */void mp3::my_init(){    pid = 0;                     // 播放進程ID    m_mtime = 0;                 // 上句歌曲時間,從0開始    m_state = 0;    pthis = this;    fp = NULL;                   // 歌詞檔案    memset(m_lyric,0,sizeof(m_lyric));   // 上一句歌詞為空白    init_music_list();      // 播放清單    connect(&m_lyric_timer,SIGNAL(timeout()),this,SLOT(show_lyric()));  //  connect(this,SIGNAL(child_exit()),this,SLOT(next_music()));    struct sigaction act;    act.sa_handler = sig_fun;    sigaction(SIGCHLD,&act,NULL);            // 播放進程退出 訊號處理函數}void mp3::next_music(){    on_xyspushButton_clicked();}void mp3::init_music_list(){    int row = ui->namelistWidget->currentRow();     // 儲存當前選中的歌    ui->namelistWidget->clear();    char cwd_buf[80];    /* 擷取目前的目錄 */    getcwd(cwd_buf,sizeof(cwd_buf));    DIR *dir;    if((dir = opendir(cwd_buf)) == NULL) {        perror("opendir");        QString msg("開啟目錄失敗!");        ui->bbslistWidget->addItem(msg.left(11));        ui->bbslistWidget->scrollToBottom();    }    struct dirent *ptr;    QString name;    int i = 0;    /* 遍曆整個目錄 */    while((ptr = readdir(dir)) != NULL) {        /*尋找尾碼名為mp3的普通檔案  */        if((ptr->d_type == 8) && strstr(ptr->d_name,".mp3") != NULL) {           name = QString(ptr->d_name);           ui->namelistWidget->addItem(name);           ui->namelistWidget->scrollToBottom();           i++;        }    }    sprintf(cwd_buf,"共有歌曲 %d 首",i);    name = cwd_buf;    ui->bbslistWidget->clear();    ui->bbslistWidget->addItem(name.left(name.length()));    ui->bbslistWidget->scrollToBottom();    if (row<0)        row = 0;    if (ui->namelistWidget->count())        ui->namelistWidget->setCurrentRow(row);    closedir(dir);}/* 播放mp3 */void mp3::play_fun(){    if (pid) {                       // 播放進程正在運行,先殺掉        kill(pid,SIGKILL);        pid = 0;        m_mtime = 0;                 // 恢複定時器為初始狀態        m_lyric_timer.stop();    }    // 先獲得要播放歌曲的全路徑    int row = ui->namelistWidget->currentRow();    if (row == -1) {        QString qstr = "未選中歌曲";        ui->bbslistWidget->addItem(qstr.left(qstr.length()));        ui->bbslistWidget->scrollToBottom();        return;    }    QString str1 = ui->namelistWidget->item(row)->text();    QByteArray ba = str1.toLocal8Bit();    char *c_str2 = ba.data();    // 調用播放器播放   /* QStringList arguments;    arguments<<c_str2;    m_qprocess.start("madplay",arguments);    sleep(3);    execlp("madplay","madplay",c_str2,NULL);    pid = m_qprocess.pid();    cout << "ssssssss"<<endl;    if (pid == -1) {        perror("Qprocess");        return;    }*/    pid = fork();    if (pid == -1) {        perror("fork");        return;    }    if (!pid) {        execlp("madplay","madplay",c_str2,NULL);        perror("execlp madplay");        return;    }    else {        ui->bfpushButton->setText("#");        init_lyric(c_str2);   // 準備播放歌詞    }}void mp3::init_lyric(char *lrc_name){    ui->lrclistWidget->clear();    strcpy(&lrc_name[strlen(lrc_name)-4],".lrc");    fp = fopen(lrc_name,"r");    if (fp == NULL) {        QString qstr = "當前播放歌曲 ";        qstr += lrc_name;        qstr += "\n未找到歌詞\n\n\n\n\n";        ui->lrclistWidget->addItem(qstr.left(qstr.length()));        ui->lrclistWidget->scrollToBottom();        return;    }    show_lyric();}/* * 播放鍵按下 */void mp3::on_bfpushButton_clicked(){    if (pid)        m_state = 1;    if (ui->bfpushButton->text() == "#") {     // 表示播放中,則發訊號暫停        ui->bfpushButton->setText("D");        kill(pid,SIGSTOP);        return;    }    else if (pid) {    // 如果按鍵符號為D,pid不為0,則表示播放歌曲暫停中,則發訊號播放它            ui->bfpushButton->setText("#");        // 播放後將 D 改為 # 符號            kill(pid,SIGCONT);            return;        }    play_fun();            // 播放}// 歌曲列表雙擊void mp3::on_namelistWidget_doubleClicked(QModelIndex index){    if (pid)        m_state = 1;     play_fun();}// 下一首歌按下 >>void mp3::on_xyspushButton_clicked(){    if (pid)        m_state = 1;    int row = ui->namelistWidget->currentRow();    if (row == -1) {        QString qstr = "列表空";        ui->bbslistWidget->addItem(qstr.left(qstr.length()));        ui->bbslistWidget->scrollToBottom();        return;    }    else if(row == ui->namelistWidget->count()-1)//最後一首        row = 0; //移動到第一首    else        row++;    ui->namelistWidget->setCurrentRow(row);    play_fun();}// 上一首歌按下 <<void mp3::on_syspushButton_clicked(){    if (pid)        m_state = 1;    int row = ui->namelistWidget->currentRow();    if (row == -1) {        QString qstr = "列表空";        ui->bbslistWidget->addItem(qstr.left(qstr.length()));        ui->bbslistWidget->scrollToBottom();        return;    }    else if (row == 0)        row = ui->namelistWidget->count() -1;    else        row--;    ui->namelistWidget->setCurrentRow(row);    play_fun();}/* *  顯示歌詞 */void mp3::show_lyric(){    QString lyric;    if (m_mtime) {                   // 時間間隔不為0說明有內容可以輸出        lyric = QString(m_lyric);        ui->lrclistWidget->addItem(lyric.left(lyric.length()));        ui->lrclistWidget->scrollToBottom();    }    char tmp[80] = {};    if (!fgets(tmp,80,fp)) {         // 得到檔案的一行,結尾到則退出        m_mtime = 0;        m_lyric_timer.stop();        return;    }    else {        int m,s,mm;        if (tmp[1] == '0') {                       // 得到間隔時間            sscanf(tmp,"[%d:%d.%d]",&m,&s,&mm);            m_lyric_timer.start(m*60*1000+s*1000+mm*10 - m_mtime);      // 設定定時            m_mtime = m*60*1000 + s*1000 +mm*10;        }        else {            m_lyric_timer.start(100);    // 說明是開頭部分,定時為1(直接輸出)            m_mtime = 1;        }    }    strcpy(m_lyric,read_lyric(tmp));   // 將內容存在 m_lyric中,供定時響應後顯示}/* *  返回真正歌詞 */char* mp3::read_lyric(char *gc){    int begsub = 0;    if (strstr(gc,"[ti:") || strstr(gc,"[ar:") || strstr(gc,"[by:")) {        begsub = 4;        gc[strlen(gc)-3] = '\0';      // 去年前後部分        return &gc[begsub];    }    else if (strstr(gc,"[al:]"))            return " ";    else        begsub = 10;        // 去掉時間部分    gc[strlen(gc)-2] = '\0';     // 最後的擴號部分去掉    return &gc[begsub];}/* * 播放進程退出,返回SIGCHLD訊號,調用此處理函數 */void sig_fun(int signum){    cout<<"SIGCHLD"<<endl;    if (!pthis->pid)        return;    if (pthis->m_state) {          // 判斷是否正常退出        pthis->m_state = 0;        return;    }    pthis->next_music();          // 正常退出則播放下一首}/********************************* 網路 *********************************/char* acp_fun(char *name,char *buf,int fds){    int fd;    if ((fd = open(name,O_CREAT | O_RDWR,777)) == -1) {        cout<<"建立 mp3 檔案失敗"<<endl;        perror("open");        return NULL;    }    while (1) {        write(fd,&buf[4],*(int*)buf);        printf("%d\n",*(int*)buf);        if (!recv(fds,buf,BUF_SIZE,0)) {            cout<<"與伺服器中斷連線"<<endl;            perror("recv");            close(fd);            return NULL;        }        if (!strcmp("#end",buf)) {            cout<<"歌曲下載完畢"<<endl;            close(fd);            system("chmod 777 笑紅塵.mp3");            return NULL;        }    }}void* net_fun(void *arg){    //pthread_detach(pthread_self());    char name[] = "笑紅塵.mp3";    int fds = socket(AF_INET,SOCK_STREAM,0);  // 建立通訊端    struct sockaddr_in saddr;    saddr.sin_family = AF_INET;    saddr.sin_port = htons(1988);    saddr.sin_addr.s_addr = inet_addr("192.168.1.200");    if (!connect(fds,(struct sockaddr*)&saddr,sizeof(saddr))) {        cout<<"串連網路成功!"<<endl;  // 串連    }    else {        cout<<"串連網路失敗!"<<endl;        perror("connect");        return NULL;    }    char buf[BUF_SIZE];    strcpy(buf,(char*)name);    if (send(fds,buf,BUF_SIZE,0) == -1) {        cout<<"發送歌曲名失敗"<<endl;        perror("send");        return NULL;    }    if (!recv(fds,buf,sizeof(buf),0)) {        cout<<"與伺服器中斷連線"<<endl;        return NULL;    }    if (!strcmp("#NULL",buf)) {        cout<<"未找到歌曲"<<endl;        return NULL;    }    acp_fun((char*)name,buf,fds);    close(fds);    return NULL;}void mp3::on_yljpushButton_clicked(){    if (pid)        m_state = 1;    pthread_t tid;                              // 從伺服器下載歌曲    pthread_create(&tid,NULL,net_fun,NULL);     // 這裡設定引一個參數為NULL會出段錯誤}void mp3::on_yljpushButton_2_clicked(){    init_music_list();                        // 更新播放清單}

伺服器部分(提供mp3下載)

#include <stdio.h>#include <string.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdlib.h>#include <vector>#include <pthread.h>using namespace std;#define BUF_SIZE 512typedef struct args{    char buf[BUF_SIZE];    int fds;}ARGS;void *tfun(void *arg){    ARGS *args = (ARGS*)arg;    printf("將開啟檔案%s\n",args->buf);      int fd = open(args->buf,O_RDWR,0777);    if (fd == -1) {        printf("open error\n");        strcpy(args->buf,"#NULL");                      // 開啟檔案失敗,則發送未找到歌曲提示        send(args->fds,args->buf,BUF_SIZE,0);         return NULL;    }    int len = 0;    while ((len = read(fd,&args->buf[4],BUF_SIZE-4)) > 0) {     // 發送全部檔案內容        write(1,&args->buf[4],*args->buf);        *(int*)args->buf = len;        printf("%d   %d\n",len,*(int*)args->buf);        if (send(args->fds,args->buf,BUF_SIZE,0) <= 0)            return NULL;    }    strcpy(args->buf,"#end");                          // 發送結束提示    send(args->fds,args->buf,BUF_SIZE,0);    printf("傳送檔案完畢\n");    delete args;}void therd_fun(int fd,char *t_buf){    ARGS *args =new ARGS;    strcpy(args->buf,t_buf);  // 儲存歌曲名    args->fds = fd;                // 連結對像的檔案描述符    pthread_t t;    pthread_create(&t, NULL,tfun,args);   // 建立線程}int main(int argc, char* argv[]){    int fds_server = socket(AF_INET,SOCK_STREAM,0); // 建立通訊端    struct sockaddr_in saddr_server;    saddr_server.sin_family = AF_INET;    saddr_server.sin_port = htons(1988);    saddr_server.sin_addr.s_addr = inet_addr("192.168.1.200");        if(bind(fds_server,(struct sockaddr*)&saddr_server,sizeof(struct sockaddr_in))) {        printf("bind error!\n");  // 綁定        return -1;    }    listen(fds_server,5);  // 設為監聽            fd_set set_read;    int fds_hwm = fds_server;   // 最大檔案描述符    int fds_client = -1;    struct sockaddr_in saddr_client;    socklen_t len;    vector<int> v_fd;             // 容器 儲存串連    vector<int>::iterator ite;    char buf[BUF_SIZE];    while (1) {        FD_ZERO(&set_read); // 初始化讀        FD_SET(fds_server,&set_read);          ite = v_fd.begin();        while (ite != v_fd.end()) {  // 將串連進的檔案描述符放入            FD_SET(*ite,&set_read);            ite++;        }        select(fds_hwm+1,&set_read,NULL,NULL,NULL);        // 有串連        if (FD_ISSET(fds_server,&set_read)) {               fds_client = accept(fds_server,(struct sockaddr*) &saddr_client,&len);            v_fd.push_back(fds_client);            printf("有新串連\n");            if (fds_hwm < fds_client)                fds_hwm = fds_client;        }        // 可讀         ite = v_fd.begin();        while (ite != v_fd.end()) {      // 遍曆            if (FD_ISSET(*ite,&set_read))                if (!recv(*ite,buf,BUF_SIZE,0)) {    // 有串連斷開                                     if (fds_hwm == fds_client)                        fds_hwm--;                    else                       ;                    printf("有串連斷開\n");                    v_fd.erase(ite);                    continue;                }                else                     therd_fun(*ite,buf);  // 有傳送 MP3 請求,建議線程處理            ite++;        }    }}

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.