原创 国嵌mp3播放器应用程序

2012-7-5 19:43 2190 15 15 分类: MCU/ 嵌入式

1.掌握双向循环链表,对指针,结构体,动态分配内存等C语言要求较高

2.掌握多进程编程,以及共享内存通信相关方面的内容

 

 


/*
 *     mp3播放器控制程序
 *    功能:
     k1:播放、暂停
     k2:停止播放
     k3:上一首
     k4:下一首
 *     附加:歌曲自动循环播放
 *
 */


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

 


/*共享内存申请标记*/
#define PERM S_IRUSR|S_IWUSR             

/*双向循环列表:存放歌曲名*/
struct song    
{
 char songname[20];
 struct song *prev;
 struct song *next;
};

/*孙子进程id号*/
pid_t gradchild;

/*子进程id号*/
pid_t pid;

/*共享内存描述标记*/
int shmid;

char *p_addr;

/*播放标记*/
int first_key=1;
int play_flag=0;

/*************************************************
Function name: play
Parameter    : struct song *
Description  : 播放函数
Return   : void
Argument     : void
Autor & date : ada 09,12,07
**************************************************/

#if 1
void play(struct song *currentsong)
{
 pid_t fd;
 char *c_addr;
 char *p;
 int len;
 char my_song[30]="/mp3/song/";
 
 while(currentsong)
 {
  /*创建子进程,即孙子进程*/
  fd = fork();
  
  if(fd == -1)
  { 
   perror("fork");
   exit(1);
  }
  else if(fd == 0)
  {
   
   //--------------------------------------------------------
   printf("child2 PID:%d\n", getpid());  //子进程ID
   //--------------------------------------------------------
   
   /*把歌曲名加上根路径*/
   strcat(my_song,currentsong->songname);
   p = my_song;
   len = strlen(p);

   /*去掉文件名最后的'\n'*/
   my_song[len-1]='\0';

   printf("THIS SONG IS %s\n",my_song);
   

   
   
   execl("/mp3/madplay","madplay",my_song,NULL);
   printf("\n\n\n");
   
   //----------------------------------------------------
   printf("execl(/mp3/madplay madplay)\n");
   
   
   

  }
  else
  {
   
 
   //------------------------------------------------------------
   printf("parent2 PID:%d\n", getpid());  //父进程ID
   //------------------------------------------------------------
  
   
   /*内存映射*/
   c_addr = shmat(shmid,0,0);

   
   //fd = 55;
   /*把孙子进程的id和当前播放歌曲的节点指针传入共享内存*/
   memcpy(c_addr,&fd,sizeof(pid_t));    //孙子进程的ID号拷贝到共享内存  
   
   memcpy(c_addr + sizeof(pid_t)+1,¤tsong,4);
   /*使用wait阻塞子进程,直到子进程播放完才能被唤醒;
     当被唤醒时,表示播放MP3期间没有按键按下,则继续顺序播放下一首MP3*/
   

   
   if(fd == wait(NULL))
   {
    currentsong = currentsong->next;
    printf("THE NEXT SONG IS %s\n",currentsong->songname);
   }
   
   
   
   //----------------------------------------------------
   printf("if(fd == wait(NULL))\n");
   
  }
 }
}
#endif

/*************************************************
Function name: creat_song_list
Parameter    : void
Description  : 创建歌曲名的双向循环链表
Return   : struct song *
Argument     : void
Autor & date : ada 09.12.07
**************************************************/
//    
//    p2    p1                        
//       -----   -----   
//  |     |    |     |  
//  |fwd--|---->|fwd  |  
//  |-----|     |-----|  
//  |     |     |     |  
//  |  bwd|<----|--bwd|  
//  |-----|     |-----|  
//  |     |     |     |  
//  |value|     |value|  
//  |-----|     |-----|

struct song *creat_song_list(void)

 FILE *fd;
 size_t size;
 size_t len;
 char *line = NULL;
 struct song *head;
 struct song *p1;
 struct song *p2;
 
 system("ls /mp3/song >song_list");
 fd = fopen("song_list","r");

 p1 = (struct song *)malloc(sizeof(struct song));

 printf("==================================song list=====================================\n");
 system("ls /mp3/song"); 
 printf("\n");
 printf("================================================================================\n");
 
 //ssize_t getline(char **lineptr, size_t *n, FILE *stream)
 size = getline(&line,&len,fd);
  
 
 #if 0 
  printf("size = %d\n",size);  //读取成功返回读取的字节数,失败返回-1 
  printf("line = %s\n",line);  //存放第一行的首地址
  printf("len = %d\n",len);  //每一行分配的字节数 
 
  size_t length = strlen(line);
  
  printf("length = %d\n",length);
  printf("----------------------------\n")
 
 #endif 
 
 //char *strncpy(char *dest, const char *src, size_t n);
 strncpy(p1->songname,line,strlen(line));
 
 head = p1;
 
 while((size = getline(&line,&len,fd)) != -1)
 { 
  p2 = p1;            //p2表示上一个结点          
  p1 = (struct song *)malloc(sizeof(struct song));  //p1表示当前结点

  //------------------------------------------
  printf("p1 = %d\n",p1);
    
  strncpy(p1->songname,line,strlen(line));
  
  //------------------------------------------
  printf("p1->songname = %s\n",p1->songname);

    
  p2->next = p1;    //p2--->p1
  
  p1->prev = p2;    //p2<---p1 
  
  //-----------------------------------------------
  printf("size = %d\n",size);  //读取的字节数 
  printf("line = %s\n",line);  //存放第一行的首地址
  printf("len = %d\n",len);  //每一行分配的字节数 
 
  size_t length = strlen(line);
  
  printf("length = %d\n",length);
  printf("----------------------------\n");
    
 }
 
 p1->next = head;     //尾结点指向首结点       
 head->prev = p1;     //
 
 p1 = NULL;
 p2 = NULL;
 
 system("rm -rf /mp3/song/song_list");
 
 return head;
}
/*************************************************
Function name: startplay
Parameter    : pid_t *,struct song *
Description  : 开始播放函数
Return   : void
Argument     : void
Autor & date : ada 09.12.07
**************************************************/
void startplay(pid_t *childpid,struct song *my_song)
{
 pid_t pid;
 int ret;
 /*创建子进程*/
 pid = fork();

 if(pid > 0)    
 {
  //------------------------------------------------------
  printf("parent1 PID:%d\n", getpid());  //父进程ID
    //------------------------------------------------------
  printf("pid PID:%d\n", pid);    //进程ID  
  //------------------------------------------------------
  
  
  
  *childpid = pid;
  play_flag = 1;
  //sleep(1);
  
  /*把孙子进程的pid号传给父进程*/
  memcpy(&gradchild,p_addr,sizeof(pid_t));
  

  printf("gradchild = %d\n",gradchild);  //孙子进程的ID号
  
 }
 else if(0 == pid)
 { 
  
  //------------------------------------------------------
  printf("child1 PID:%d\n", getpid());  //子进程ID
  //------------------------------------------------------
  
  /*子进程播放MP3函数*/
  play(my_song);
  
  
 }
}
/*************************************************
Function name: my_pause
Parameter    : pid_t
Description  : 暂停函数
Return   : void
Argument     : void
Autor & date : ada 09,12,07
**************************************************/
void my_pause(pid_t pid)
{
 printf("=======================PAUSE!PRESS K1 TO CONTINUE===================\n");
 kill(pid,SIGSTOP); //对孙子进程发送SKGSTOP信号
 play_flag = 0;
}

/*************************************************
Function name: my_pause
Parameter    : pid_t
Description  : 停止播放函数
Return   : void
Argument     : void
Autor & date : ada 09,12,07
**************************************************/
void my_stop(pid_t g_pid)
{

 printf("=======================STOP!PRESS K1 TO START PLAY===================\n");
 kill(g_pid,SIGKILL); //对孙子进程发送SKGKILL信号
 kill(pid,SIGKILL);   //对子进程发送SKGKILL信号
 first_key=1;

}

/*************************************************
Function name: conti_play
Parameter    : pid_t
Description  : 继续函数
Return   : void
Argument     : void
Autor & date : ada 09,12,07
**************************************************/
void conti_play(pid_t pid)
{
 printf("===============================CONTINUE=============================\n");
 kill(pid,SIGCONT); //对孙子进程发送SIGCONT信号
 play_flag=1;
}

/*************************************************
Function name: next
Parameter    : pid_t
Description  : 下一首函数
Return   : void
Argument     : void
Autor & date : ada 09.12.07
**************************************************/
void next(pid_t next_pid)
{
 struct song *nextsong;

 printf("===============================NEXT MP3=============================\n");
 
 /*从共享内存获得孙子进程播放歌曲的节点指针*/
 memcpy(&nextsong,p_addr + sizeof(pid_t)+1,4);
 
 /*指向下首歌曲的节点*/
 nextsong = nextsong->next;
 
 /*杀死当前歌曲播放的子进程,孙子进程*/
 kill(pid,SIGKILL);
 
 kill(next_pid,SIGKILL);
 
 wait(NULL);
 
 startplay(&pid,nextsong);
}

/*************************************************
Function name: prev
Parameter    : pid_t
Description  : 上一首函数
Return   : void
Argument     : void
Autor & date : yuanhui 09.12.08
**************************************************/
void prev(pid_t prev_pid)
{
 struct song *prevsong;
 
 /*从共享内存获得孙子进程播放歌曲的节点指针*/
 printf("===============================PRIOR MP3=============================\n");
 
 memcpy(&prevsong,p_addr + sizeof(pid_t)+1,4);
 
 /*指向上首歌曲的节点*/
 prevsong = prevsong->prev;
 
 /*杀死当前歌曲播放的子进程,孙子进程*/
 kill(pid,SIGKILL);
 
 kill(prev_pid,SIGKILL);
 
 wait(NULL);
 
 startplay(&pid,prevsong);
}

 

 

 

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
15
关闭 站长推荐上一条 /3 下一条