首先创建vim main.c初始化设备文件
#include <stdio.h>
int g_buttonfd ;
int g_ledfd;
int g_mixerfd;
int main()
{
InitDriver();
return 0;
}
按键设备文件,用于操作硬件设备
vim deviece.c
//用于操作硬件设备
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#
extern int g_buttonfd;
extern int g_ledfd;
extern int g_mixerfd;
int InitDriver()
{
//打开按键设备文件
g_buttonfd = open("/dev/buttons", O_RDONLY);
if (-1 == g_buttonfd)
{
return FAILURE;
}
//打开led设备文件
g_ledfd = open("/dev/leds", O_WRONLY);
if (-1 == g_ledfd)
{
return FAILURE;
}
//打开minxer设备文件
g_mixerfd = open("/dev/mixer", O_WRONLY);
if (-1 == g_mixerfd)
{
return FAILURE;
}
return SUCCESS;
}
新建vim main.h
#ifndef MAIN_H
#define MAIN_H
#define SUCCESS 10000
#define FAILURE 10001
#endif
声明设备头文件vim devide.h
#ifndef DEVICE_H
#define DEVICE_H
int InitDriver();
#endif
对主函数做返回值判断main.c
#include <stdio.h>
int g_buttonfd ;
int g_ledfd;
int g_mixerfd;
int main()
{
int ret;
ret = InitDriver(); //打开设备文件
if (FAILURE == ret)
{
printf("初始化设备文件失败\n");
exit(1);
}
return 0;
}
设备初始化完后对网络进行初始化
#include <stdio.h>
int g_buttonfd ;
int g_ledfd;
int g_mixerfd;
int main()
{
int ret;
ret = InitDriver(); //打开设备文件
if (FAILURE == ret)
{
printf("初始化设备文件失败\n");
exit(1);
}
ret = InitSocket(); //初始化网络
if (FAILURE == ret)
{
printf("初始化网络失败\n");
//初始化失败,点亮 2 个LED灯
led_on(0);
led_on(1);
}
return 0;
}
下面实现网络初始化代码:
vim socket.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "main.h"
int InitSocket()
{
g_sockfd = socket(PF_INET, SOCK_STREAM, 0);
if (-1 == g_sockfd)
{
return FAILURE;
}
}
socket头文件socket.h
#ifndef SOCKET_H
#define SOCKET_H
#define SERVER_PORT 8000
#define SERVER_IP "47.101.128.140"
int InitSocket();
#endif
当socket创建好后,启动线程发起服务器连接
socket.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "main.h"
extern int g_sokcetfd;
int InitSocket()
{
g_sockfd = socket(PF_INET, SOCK_STREAM, 0);
if (-1 == g_sockfd)
{
return FAILURE;
}
pthread_t tid;
int ret = pthread_create(&tid, NULL, connect_cb, NULL);
if (ret != 0)
{
return FAILURE;
}
}
创建线程后启动一个线程函数connect_cb
void *connect_cb(void *arg)
{
int count = 5, ret;
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = PF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
while (count--)
{
ret = connect(g_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret == -1)
{
sleep(5);
continue;
}
//连接成功,点亮 4 个LED灯
led_on(0);
led_on(1);
led_on(2);
led_on(3);
break;
}
return NULL;
}
考虑到会连接失败,线程会向服务器发起5次连接,如果五次均为成功,返回失败。
因为开发板有led,现在考虑连接的时候用led提示,发起连接的时候第一个灯亮,初始化时led灭,
连接成功4个灯都亮
device.c
//所有LED灭
int i;
for (i = 0; i < 4; i++)
{
ioctl(g_ledfd, 0, i);
}
void led_on(int which)
{
ioctl(g_ledfd, 1, which);
}
void led_off(int which)
{
ioctl(g_ledfd, 0, which);
}
device.h
#ifndef DEVICE_H
#define DEVICE_H
int InitDriver();
int led_on(int which);
int led_off(int which);
#endif
在socket.c加入device.h头文件
#include <sys/socket.h>
#include "main.h"
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include "device.h"
在main.c中做一个判断,当网络初始化失败后亮两个灯
ret = InitSocket(); //初始化网络
if (FAILURE == ret)
{
printf("初始化网络失败\n");
//初始化失败,点亮 2 个LED灯
led_on(0);
led_on(1);
}
初始化网络,一旦连接成功后,下面就要监听,到底是按键还是网络有信息发过来
音箱的触发要么是按键触发g_buttonfd,要么是app触发g_sockfd
下面写一个函数采用select复用io来监听fd
在main.c中
m_select();
新建一个vim selec.c
#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
extern int g_buttonfd;
extern int g_sockfd;
void show()
{
printf("1、开始播放\n");
printf("2、结束播放\n");
printf("3、暂停播放\n");
printf("4、继续播放\n");
printf("5、上一首\n");
printf("6、下一首\n");
printf("7、增加音量\n");
printf("8、减小音量\n");
printf("9、顺序播放\n");
printf("a、随即播放\n");
printf("b、单曲循环\n");
}
void m_select()
{
show();
fd_set readfd, tmpfd;
int ret;
int maxfd = (g_buttonfd > g_sockfd) ? g_buttonfd : g_sockfd;
FD_ZERO(&readfd);
FD_ZERO(&tmpfd);
FD_SET(g_buttonfd, &readfd);
FD_SET(g_sockfd, &readfd);
FD_SET(0, &readfd);//标准输入添加到集合,调试用
while (1)
{
tmpfd = readfd;
ret = select(g_maxfd + 1, &tmpfd, NULL, NULL, NULL);
if (-1 == ret && errno != EINTR)
{
perror("select");
}
else if (-1 == ret && errno == EINTR)
{
continue;
}
if (FD_ISSET(g_sockfd, &tmpfd)) //TCP有数据可读
{
}
else if (FD_ISSET(g_buttonfd, &tmpfd)) //按键有数据可读
{
}
}
}
再开始播放音乐的时候,需要把所有音乐的名字读出来。
main.c
//读取音乐
GetMusic();
音乐的名字用链表来存储,需要初始化链表
vim main.c中
#include "main.h"
#include "device.h"
#include <stdlib.h>
int g_buttonfd ;
int g_ledfd;
int g_mixerfd;
int g_sockfd ;
struct Node *head;
int main()
{
//初始化链表
ret = InitLink();
if (FAILURE == ret)
{
printf("链表初始化失败\n");
exit(1);
}
}
新建一个链表link.h头文件
#ifndef LINK_H
#define LINK_H
struct Node
{
char music_name[64];
struct Node *next;
};
typedef struct Node Node;
int InitLink();
#endif
初始化链表link.c
#include <stdio.h>
#include <stdlib.h>
#include "main.h"
#include <string.h>
#include "link.h"
extern struct Node *head;
//初始化链表
int InitLink()
{
head = (Node *)malloc(sizeof(Node) * 1);
if (NULL == head)
{
return FAILURE;
}
head->next = NULL;
return SUCCESS;
}
下面要读取音乐vim player.h
#ifndef PLAYER_H
#define PLAYER_H
#include <unistd.h>
#define MUSICPATH "/root/music_list/"
//测试中音乐所在文件目录
#endif
下面需要从目录中获取音乐的名字放在链表中,打开目录用opendir
vim player.c
#include <stdio.h>
#include "link.h"
#include "main.h"
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>
#include "player.h"
extern Node *head;
void GetMusic()
{
//打开目录
DIR *dir = opendir(MUSICPATH);
if (NULL == dir)
{
perror("opendir");
exit(1);
}
struct dirent *file = NULL;
//读取目录
while ((file = readdir(dir)) != NULL)
{
if (file->d_type != 8) //不是普通文件
{
continue;
}
if (!m_mp3_end(file->d_name)) //不是mp3文件
{
continue;
}
printf("%s\n", file->d_name); //如果是.mp3结尾,输出读取到的文件名字
int ret = InsertLink(head, file->d_name); //把音乐名字插入到链表
if (FAILURE == ret)
{
printf("歌曲插入失败\n");
exit(1);
}
}
}
判断歌曲是不是.mp3结尾是返回1不是返回0,m_mp3_end
//判断是不是.mp3结尾
int m_mp3_end(const char *name)
{
const char *ptr = name; //传进来的文件名字
while (*ptr != '\0') //循环到文件名字末尾
{
ptr++;
}
int i;
for (i = 0; i < 4; i++) //因为现在ptr在\0位置,所以需要往前走四个位置定位到。MP3,运行结束在.位置
{
ptr--;
}
if (ptr < name)
return 0;
return (strcmp(ptr, ".mp3") == 0) ? 1 : 0; //判断是不是.mp3
}
vim link.c
int InsertLink(Node *h, const char *name)
{
if (NULL == h || NULL == name) //链表初始化失败为空或者传入文件名有问题为空
{
return FAILURE;
}
Node *p = h; //新建节点指向头结点
while(p->next)
{
p=p->next; // 定位到链表最后一个位置
}
Node *n = (Node *)malloc(sizeof(Node) * 1);
if (NULL == n)
{
return FAILURE;
}
n->next = h;
strcpy(n->music_name, name); //将音乐的名字写道新建的节点中
p->next = n;
return SUCCESS;
}
在select.c中加一个标准输入 的测试代码,后续会删除,主要用于测试功能
#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
extern int g_buttonfd;
extern int g_sockfd;
void show()
{
printf("1、开始播放\n");
printf("2、结束播放\n");
printf("3、暂停播放\n");
printf("4、继续播放\n");
printf("5、上一首\n");
printf("6、下一首\n");
printf("7、增加音量\n");
printf("8、减小音量\n");
printf("9、顺序播放\n");
printf("a、随即播放\n");
printf("b、单曲循环\n");
}
void m_select()
{
show();
fd_set readfd, tmpfd;
int ret;
int maxfd = (g_buttonfd > g_sockfd) ? g_buttonfd : g_sockfd;
FD_ZERO(&readfd);
FD_ZERO(&tmpfd);
FD_SET(g_buttonfd, &readfd);
FD_SET(g_sockfd, &readfd);
FD_SET(0, &readfd);//标准输入添加到集合,调试用
while (1)
{
tmpfd = readfd;
ret = select(g_maxfd + 1, &tmpfd, NULL, NULL, NULL);
if (-1 == ret && errno != EINTR)
{
perror("select");
}
else if (-1 == ret && errno == EINTR)
{
continue;
}
if (FD_ISSET(g_sockfd, &tmpfd)) //TCP有数据可读
{
}
else if (FD_ISSET(g_buttonfd, &tmpfd)) //按键有数据可读
{
}
else if(FD_ISSET(0, &tmpfd)
{
int func;
scanf(“%d”,&func);
switch(func)
{
case 1:
break;
case2:
break;
}
}
}
}