天天看點

MPlayer 音樂播放器項目講解MPlayer 音樂播放器項目講解

MPlayer 音樂播放器項目講解

一、簡要介紹MPlyer音樂播放器

MPlayer是一款開源多媒體播放器,以GNU通用公共許可證釋出。此款軟體可在各主流操作系 統使用,例如Linux和其他類Unix系統、Windows及Mac OSX
系統。
           

二、在開發闆實作MPlayer功能

具體如何實作mute 0 靜音,為什麼用這個指令不用我們做,我們要做的是在開發闆上擷取出界面後,按下相應按鈕實作相應的功能,即對這個指令的處理和
調用。完成的效果圖如下:
           
MPlayer 音樂播放器項目講解MPlayer 音樂播放器項目講解

三、 Mplayer 項目規格

mplayer 的基本功能(必做部分)
	1、能夠播放歌曲檔案
	2、能通過觸摸屏按鈕控制mplayer 播放、暫停、上一首、下一首、音量加減
	3、顯示歌曲清單,目前播放歌曲須要反顯,點選對應歌曲能切換
	4、顯示歌曲資訊
	(歌曲總長度、歌曲目前播放時間、歌曲進度百分比、歌曲名字、歌曲藝術家)
	5、顯示歌曲對應的歌詞,并且能夠和歌曲同步
	6、能夠自動換歌(播放完一首歌曲後,自動播放下一首歌)
           

四、思路

MPlayer 音樂播放器項目講解MPlayer 音樂播放器項目講解

五、具體操作步驟

1、畫glade界面

MPlayer 音樂播放器項目講解MPlayer 音樂播放器項目講解
具體架構:
 #include<gtk/gtk.h>//頭檔案
  int main(int argc,char &argv)
{
	gtk_init(&argc,&argv);
	GladeXML *gxml = glade_xml_new("./mplayer.glade",NULL,NULL);
	//打開glade檔案;
	//......
	//我們所寫的代碼
	//.....
	gtk_main();
	return 0;
}
   添加代碼後的運作效果:
           
MPlayer 音樂播放器項目講解MPlayer 音樂播放器項目講解

2、主函數分為父、子程序

父程序: 開啟mplayer,用到execlp指令
     子程序:
             (1)搭GTK架構,建立背景視窗、布局以及控件的擷取顯示;
             (2) 寫上一首、下一首、暫停的回調函數(g_signal_connect);
             (3) 擷取歌曲目錄資訊;
              DIR *dir;
              struct dirent *dirp;
              int i = 0;
              char *dd[100]={};
              char ll[100]="";
              if((dir=opendir("./song"))==NULL)
               {
                     printf("Open dir song fail\n");
                     exit(1);
               }
               while((dirp=readdir(dir))!=NULL)
               {
                   song_list[i]=(char*)malloc(sizeof(dirp->d_name)+1);
                   strcpy(song_list[i],dirp->d_name);
                   printf("%s\n",song_list[i]);
                   i++;
                   a.geshu=i;
                   printf("%d\n",i);
                 }
                 closedir(dir);
           (4)音量鍵
   void eventbox_volume(GtkWidget *widget, GdkEventButton *event, gpointer data)  
 {
	WIN *a = (WIN *)data;
	static gboolean is_press = TRUE;
	if(event->y>=93&&event->y <=168)
	{
		if(TRUE == is_press)
		{
			int fd = open("./fifo",O_RDWR);
			load_image(a->image_volume, "./mplayer/muteoff.jpg",89,75);
			write(fd,"mute 1\n",strlen("mute 1\n"));
			is_press = FALSE;
			close(fd);
		}else
		{
			int fd2 = open("./fifo",O_RDWR);
			load_image(a->image_volume, "./mplayer/mute.jpg",89,75);
			write(fd2,"mute 0\n",strlen("mute 0\n"));
			is_press = TRUE;
			close(fd2);
		}
	 }
	if(event->y>=1&&event->y<=90)
	{	
		char buf[100]="";
		int gg=90-event->y;
		sprintf(buf,"volume %d 1\n",gg);
		int fd3=open("./fifo",O_RDWR);
		write(fd3,buf,strlen(buf));
		close(fd3);
		gtk_progress_bar_set_fraction((GtkProgressBar *)a->lable_voice,gg/89.0);
	}	
}
           

3、做歌曲名、歌手、歌曲目前位置、歌曲長度、播放進度顯示

線程1:不停發指令,列印到螢幕上,寫到父程序裡(while(1)循環指令),為了不讓列印到電腦上,要重定向到管道中(dup指令)
      void *fun1(void *arg)
	{
		WIN *a = (void *)arg;
		int fd2 = open("./fifo",O_RDWR);
		while(1)
			{
			usleep(50000);
				if(zz==0)
				{
					write(fd2,"get_time_pos\n",strlen("get_time_pos\n"));
					write(fd2,"get_meta_artist\n",strlen("get_meta_artist\n"));
					write(fd2,"get_file_name\n",strlen("get_file_name\n"));
					
					write(fd2,"get_time_length\n",strlen("get_time_length\n"));
					write(fd2,"get_percent_pos\n",strlen("get_percent_pos\n"));
				}				
			}
		close(fd2);
	}
      線程2:不停去管道中讀資料,做處理
                    (1)if語句做判斷
                    (2)sscanf做切割
                    (3)進行組包
                    (4)gtk_label_set_text設定label标簽的内容,箭頭指向(如:gtk_label_set_text(a->label_cur_time,buff))
        void *fun2(void *arg)
	{
		WIN *a = (void *)arg;
		char *b;
		char *c;
		char *d;
		char *e;
		char *f;
		while(1)
		{
			char buf[100]="";
			int shijian;
			char artist[200];
			char filename[200];		
			read(a->fd[0],buf,sizeof(buf));
			if(strstr(buf,"ANS_TIME_POSITION"))
			{
				b = strstr(buf,"ANS_TIME_POSITION");
				sscanf(b,"ANS_TIME_POSITION=%d",&shijian);
				a->time=shijian;
				char buff[100]="";
				sprintf(buff,"%02d:%02d",shijian/60,shijian%60);
				gdk_threads_enter();
				gtk_label_set_text(a->label_cur_time,buff);
				gdk_threads_leave();
			}		 
			if( strstr(buf,"ANS_META_ARTIST")   )
		 {
			c = strstr(buf,"ANS_META_ARTIST");
			sscanf(c,"ANS_META_ARTIST='%[^']",&artist);
			char utf8_temp[100] = "";	
			gb2312_to_utf8(artist, utf8_temp);			
			gdk_threads_enter();
			gtk_label_set_text(a->label_singer,utf8_temp);
			gdk_threads_leave();
	 	}
	 	if(strstr(buf,"ANS_FILENAME"))
	{
		d = strstr(buf,"ANS_FILENAME");
		sscanf(d,"ANS_FILENAME='%[^']",&filename);		
		gdk_threads_enter();
		gtk_label_set_text(a->label_song,filename);
		gdk_threads_leave();
	}	
	if(strstr(buf,"ANS_LENGTH"))
	{
		int zong;
		e=strstr(buf,"ANS_LENGTH");
		sscanf(e,"ANS_LENGTH=%d",&zong);
		a->song_length=zong;
		char buff2[100]="";
		sprintf(buff2,"%02d:%02d",zong/60,zong%60);
		gdk_threads_enter();
		gtk_label_set_text(a->label_len_time,buff2);
		gdk_threads_leave();	
	}	
	if(strstr(buf,"ANS_PERCENT_POSITION"))
	{
		int zong2;
		f=strstr(buf,"ANS_PERCENT_POSITION");
		sscanf(f,"ANS_PERCENT_POSITION=%d",&zong2);	
		gtk_progress_bar_set_fraction((GtkProgressBar *)a->progressbar_rate,zong2/100.0);
		
	}	
	if(((a->time)+290)==(a->song_length-10))//播放到百分之多少的時候自動切換歌曲
	{
		if(qq==0)//如果是播放狀态就切,不是就不切
		{
			sleep(1);
			button_next(NULL,k);
			sleep(1);
		}
		qq=1;
	}	
}
           

4、線程3歌詞顯示

(1)有一個歌詞檔案
         (2)歌詞檔案解析,存連結清單(将時間與歌詞進行比對)
      重點:首先找到目前播放的歌,拿目前的時間與歌次做比較比對資訊
void *fun3(void *arg)//同步歌詞。因為歌詞不能去問mplayer
{
	WIN *a = (void *)arg;
	while(1)
	{
		LRC_PTR lrc;
		LRC *head = NULL;
		char buf[100]="";
		char song_list_my[100];
	
		sscanf(song_list[k],"%[^.mp3]",song_list_my);
		printf("%d\n",k);
		sprintf(buf,"./songci/%s.lrc",song_list_my);
		head = dispose_lrc(buf, &lrc);
		if(head == NULL)//解析歌詞失敗
		{
			printf("No this lyrics\n");
		}
		else
		{
			int i;
			for(i=0;i<lrc.lrc_arry_size;i++)//時間是毫秒ms
			{
				if(lrc.lrc_arry[i]->time/1000==a->time)//時間與我們的歌詞檔案的每一句歌詞時間比對
				{
					char utf8_temp[1000] = "";
					gb2312_to_utf8(lrc.lrc_arry[i]->lrc, utf8_temp);//轉碼
					gdk_threads_enter();
					gtk_label_set_text(a->label_lrc,utf8_temp);//寫入歌詞label
					gdk_threads_leave();
				}
			}
		}
		free_lrc_arry(&lrc);
	}	
}
           

繼續閱讀