Linux音乐电子相册(相册部分)

//编译后的程序需与图片放置于同一文件夹,开始、退出界面图片在上一级目录,具体路径请自行配置

#include 
#include 
#include   //mmap();   munmap();
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include   //SIGCHLD变量头文件
#include 

#define HEIGHT 480  //屏幕分辨率
#define LENGTH 800

#define DAEMON 120

#define PICDIR "/usr/lcd/gal"  //图片路径
#define PICNUM 9  //BMP图片数目
#define THNUM 4  //线程数
#define BEGIN "../pic0.bmp"  //开始界面图片路径
#define END "../pic9.bmp" //退出界面图片路径

#define LCD "/dev/fb0"  //LCD设备路径
#define KEY "/dev/event1"  //键盘设备路径

#define UPS SIGRTMIN+1  //上一张
#define DOWNS SIGRTMIN+2  //下一张
#define BEGINS SIGRTMIN+3  //开始
#define QUITS SIGRTMIN+4  //退出
#define RETURN SIGRTMIN+4  //返回

#define ESC 1  //各个按键的键值
#define HOME 2
#define POWER 3
#define ENTER 96
#define UP 103
#define DOWN 108
#define LEFT 105
#define RIGHT 106

struct input_event key_value;

int isEnter = 0;  //标记是否打开程序
int isOpen = 0;  //标记是否打开图片
int pageSum = 0;  //标记总页数
int page = 1;  //标记当前页号,从1开始
int choice = 0;  //标记选中哪一张图片(0-1-2-3)

FILE* bmp[PICNUM];
FILE* bmpEND;
FILE* bmpBEG;
int* fb_mem;
char buff[LENGTH * HEIGHT * 3];

pid_t pptpid;
int pptfd[2];

void DrawLCD(FILE* bmps, int x1, int x2, int y1, int y2, int z1, int z2) {  //按给定参数绘制图片
	/* x1:x起始位置;  x2:x结束位置;  y1:y起始位置;  y2:y结束位置;  z1:行偏移位置;  z2:列偏移位置
	 * 函数作用:从(x1, y1)到(x2, y2)绘制图片bmps
	 * 横向每(z1 + 1)个像素并为一个,纵向每(z2 + 1)行并为一行, z1、z2需配合x1、x2、y1和y2 */
	int x = 0;
	int y = 0; 
	int i = 0;
	fseek(bmps, 54, SEEK_SET);
	fread(buff, LENGTH * HEIGHT * 3, 1, bmps);	
	for (y = y2; y >= y1; y--) {
		for (x = x1; x <= x2; x++) {
			*(fb_mem + y * LENGTH + x) = (buff[i] << 0 | buff[i + 1] << 8 | buff[i + 2] << 16);
			i += 3 * (z1 + 1);
		}
		i += z2 * (3 * LENGTH);
	}
}

void toPage() {  //按页号将四张图片输出为一张
	if (((page - 1) * 4) > PICNUM || page <= 0) {  //超出图库范围则报错
		perror("Page Out Of Range\n");
		return;
	} else {
		//Read((0,0)~(399,239))
		DrawLCD(bmp[4 * (page - 1)], 0, LENGTH / 2 - 1, 0, HEIGHT / 2 - 1, 1, 1);  //(0, 0) -> (LENGTH / 2 - 1, HEIGHT / 2 - 1), 偏移像素1,偏移行数1
		
		//Read((400,239)~(799,239))
		if ((4 * (page - 1) + 1) < PICNUM) {
			DrawLCD(bmp[4 * (page - 1) + 1], LENGTH / 2, LENGTH - 1, 0, HEIGHT / 2 - 1, 1, 1);  //(LENGTH / 2, 0) -> (LENGTH - 1, HEIGHT / 2 - 1), 偏移像素1,偏移行数1
		} else {
			int x = 0;
			int y = 0;
			for (y = (HEIGHT / 2 - 1); y >= 0; y--) {
				for (x = LENGTH / 2; x < LENGTH; x++) {
					*(fb_mem + y * LENGTH + x) = 0xb5b5b5;
				}
			}
		}
		//Read((0,240)~(399,479))
		if ((4 * (page - 1) + 2) < PICNUM) {
			DrawLCD(bmp[4 * (page - 1) + 2], 0, LENGTH / 2 - 1, HEIGHT / 2, HEIGHT - 1, 1, 1);			
		} else {
			int x = 0;
			int y = 0;
			for (y = (HEIGHT - 1); y >= (HEIGHT / 2); y--) {
				for (x = 0; x < LENGTH / 2; x++) {
					*(fb_mem + y * LENGTH + x) = 0xaaaaaa;
				}
			}
		}
		//Read((400,479)~(799,239))
		if ((4 * (page - 1) + 3) < PICNUM) {
			DrawLCD(bmp[4 * (page - 1) + 3], LENGTH / 2, LENGTH - 1, HEIGHT / 2, HEIGHT - 1, 1, 1);
		} else {
			int x = 0;
			int y = 0;
			for (y = (HEIGHT - 1); y >= (HEIGHT / 2); y--) {
				for (x = LENGTH / 2; x < LENGTH; x++) {
					*(fb_mem + y * LENGTH + x) = 0x969696;
				}
			}
		}
	}
}

void HeightLight() {  //为选中的图片绘制红框
	if (choice >=0 && choice <= 3) {
		int i = 0;
		int offL = choice % 2;
		int offH = choice / 2;
		toPage(bmp);
		for (i = (LENGTH / 2) * offL; i < (LENGTH / 2) * (offL + 1); i++) {
			//四条横线
			*(fb_mem + ((HEIGHT / 2) * offH) * LENGTH + i) = 0xff0000;
			*(fb_mem + ((HEIGHT / 2) * offH + 1) * LENGTH + i) = 0xff0000;
			*(fb_mem + ((HEIGHT / 2) * (offH + 1) - 2) * LENGTH + i) = 0xff0000;
			*(fb_mem + ((HEIGHT / 2) * (offH + 1) - 1) * LENGTH + i) = 0xff0000;
		}
		for (i = (HEIGHT / 2) * offH + 2; i < ((HEIGHT / 2) * (offH + 1) - 2); i++) {
			//四条竖线
			*(fb_mem + i * LENGTH + (LENGTH / 2) * offL) = 0xff0000;
			*(fb_mem + i * LENGTH + (LENGTH / 2) * offL + 1) = 0xff0000;				
			*(fb_mem + i * LENGTH + (LENGTH / 2) * (offL + 1) - 1) = 0xff0000;				
			*(fb_mem + i * LENGTH + (LENGTH / 2) * (offL + 1) - 2) = 0xff0000;
		}
	}
}

void getFile(DIR* dir) {  //读取图片文件
	if (dir != NULL && bmp != NULL) {
		int i = 0;
		if (dir != NULL) {
			struct dirent* d_p;
			while ((d_p = readdir(dir)) != NULL && i < PICNUM) {
				if(strstr(d_p->d_name,".bmp")) {
					bmp[i] = fopen(d_p->d_name, "r");
					if (bmp[i] == NULL) {
						perror("Read Pic Failed!\n");
						_exit(0);
					}
					i++;
				}
			}
		}
	}
}

void key_Return() {  //返回小图模式
	if (isEnter == 1 && isOpen == 1) {
		kill(pptpid, SIGINT);
		toPage();
		HeightLight();
		isOpen = 0;
	}
}

void key_Enter() {  //进入主程序
	if (isEnter == 0) {
		//Enter
		toPage();
		HeightLight();
		isEnter = 1;
	}
}

void key_Back() {  //退出程序
	kill(pptpid, SIGINT);
	DrawLCD(bmpEND, 0, LENGTH - 1, 0, HEIGHT - 1, 0, 0);
	kill(DAEMON, QUITS);
	isEnter = 0;
	sleep(3);
}
 
void getNext(int sig) {
	if (sig == RETURN) {
		char buff[2];
		read(pptfd[0], buff, 2);
		page = buff[0];
		choice = buff[1];
	}
}
 
void pptQuit(int sig) {
	if (sig == SIGINT) {
		char buff[2];
		buff[0] = page;
		buff[1] = choice;
		write(pptfd[1], buff, 2);
		kill(getppid(), RETURN);
		exit(0);
	}
 }

void* Thread(void* p) {
	int arg = (int)p;
	int num = arg / 10;
	int method = arg % 10;
	int x = 0;
	int y = 0;
	int pos = (3 - num) * (HEIGHT / 4) * 3 * LENGTH;
	if (method == 0) {  //下向上
		for (y = (num + 1) * (HEIGHT / 4) - 1; y >= num * (HEIGHT / 4); y--) {
			for (x = 0; x <= LENGTH - 1; x++) {
				*(fb_mem + y * LENGTH + x) = (buff[pos] << 0 | buff[pos + 1] << 8 | buff[pos + 2] << 16);
				pos += 3;
			}
			usleep(3000);
		}
	} else if (method == 1) {  //左向右
		for (x = num * (LENGTH / 4); x <= (num + 1) * (LENGTH / 4) - 1; x++) {
			pos = 3 * x;
			for (y = HEIGHT - 1; y >= 0; y--) {
				*(fb_mem + y * LENGTH + x) = (buff[pos] << 0 | buff[pos + 1] << 8 | buff[pos + 2] << 16);
				pos += 3 * LENGTH;
			}
			usleep(3000);
		}
	} else if (method == 2) {  //上向下
		pos = ((4 - num) * (HEIGHT / 4) - 1) * 3 * LENGTH;  //偏移到每块的顶行
		for (y = num * (HEIGHT / 4); y <= (num + 1) * (HEIGHT / 4) - 1; y++) {
			for (x = 0; x <= LENGTH - 1; x++) {
				*(fb_mem + y * LENGTH + x) = (buff[pos] << 0 | buff[pos + 1] << 8 | buff[pos + 2] << 16);  //扫描并显示一行
				pos += 3;
			}
			pos = pos - 6 * LENGTH;  //回退两行,即刷新刚才一行的下边一行
			//不回退的话就会显示刚才一行的上一行
			usleep(3000);
		}
	} else if (method == 3) {  //右向左
		for (x = (num + 1) * (LENGTH / 4) - 1; x >= num * (LENGTH / 4); x--) {
			pos = 3 * x;
			for (y = HEIGHT - 1; y >= 0; y--) {
				*(fb_mem + y * LENGTH + x) = (buff[pos] << 0 | buff[pos + 1] << 8 | buff[pos + 2] << 16);
				pos += 3 * LENGTH;
			}
			usleep(3000);
		}
	}
	pthread_exit(NULL);
}

void DrawInWindows(FILE* bmps, int method) {
	fseek(bmps, 54, SEEK_SET);
	fread(buff, LENGTH * HEIGHT * 3, 1, bmps);
	method = method % 10;
//	method = 3;
	pthread_t pth[THNUM];
	int i = 0;
	for (i = 0; i < THNUM; i++) {
		pthread_create(&pth[i], NULL, Thread, (void*)(i * 10 + method));
	}
	for (i = 0; i < THNUM; i++) {
		pthread_join(pth[i], NULL);
	}
}

void key_Open() {  //打开选中的图片
	if (isEnter == 1 && isOpen == 0 && choice >=0 && choice <= 3) {
		//OPEN
		int method = 0;
		DrawInWindows(bmp[4 * (page - 1) + choice], method);
		pipe(pptfd);
		pptpid = fork();
		if (pptpid == 0) {
			close(pptfd[0]);
			signal(SIGINT, pptQuit);
			int current = 4 * (page - 1) + choice;
			while (1) {
				method = (method + 1) % 4;
				sleep(3);
				current = (current + 1) % PICNUM;
				page = current / 4 + 1;
				choice = current % 4;				
				DrawInWindows(bmp[current], method);
			}
		} else if (pptpid != 0) {
			close(pptfd[1]);
			isOpen = 1;
			signal(RETURN, getNext);
		}
	}
}

void key_PageUp() {  //上一页
	if (isEnter == 1 && isOpen == 0) {
		if (page <= 1) {  //已是第一页
			page = pageSum;  //跳到最后一页
		} else {
			page--;
		}
		while (4 * (page - 1) + choice >= PICNUM) {
			choice--;
		}
		toPage();
		HeightLight();
	}
}

void key_PageDown() {  //下一页
	if (isEnter == 1 && isOpen == 0) {
		if (page >= pageSum) {
			page = 1;
		} else {
			page++;
		}
		while (4 * (page - 1) + choice >= PICNUM) {
			choice--;
		}
		toPage();
		HeightLight();
	}
 }

void key_Up() {  //上一张
	if (isEnter == 1 && isOpen == 0) {
		char flag = 'n';
		if (choice <= 0) {
			choice = 3;
			flag = 'y';
		} else {
			choice--;
			flag = 'y';
		}
		while (4 * (page - 1) + choice >= PICNUM) {
			choice--;
			flag = 'n';
		}
		if (flag == 'y') {
			kill(DAEMON, UPS);
			HeightLight();
		}
	}
}

void key_Down() {  //下一张
	if (isEnter == 1 && isOpen == 0  && 4 * (page - 1) + choice < PICNUM) {
		char flag = 'n';
		if (choice >= 3) {
			choice = 0;
			flag = 'y';
		} else {
			choice++;
			flag = 'y';
		}
		while (4 * (page - 1) + choice >= PICNUM) {
			choice--;
			flag = 'n';
		}
		if (flag == 'y') {
			kill(DAEMON, DOWNS);
			HeightLight();
		}
	}
}

int main(int argc ,char **argv) {
	if ((PICNUM % 4) == 0) {
		pageSum = PICNUM / 4;
	} else {
		pageSum = PICNUM / 4 + 1;
	}


	int flag = 1;  //循环标记
	int ret = 0;
	int lcdid = open(LCD, O_RDWR);
	int fd = open(KEY, O_RDONLY);

	bmpBEG = fopen(BEGIN, "r");  //进入、退出界面
	bmpEND = fopen(END, "r");
	
	if(fd <= 2 || lcdid <= 2) {
		perror(" open !");
		return -1;
	} else {
		int x = 0;
		int y = 0;
		int i = 0;

		DIR* dir = opendir(PICDIR);
		if (dir != NULL) {
			getFile(dir);
			fb_mem = mmap(NULL, LENGTH * HEIGHT * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcdid, 0);	 
			if (fb_mem != NULL) {
				DrawLCD(bmpBEG, 0, LENGTH - 1, 0, HEIGHT - 1, 0, 0);
				kill(DAEMON, BEGINS);  //开启
				while (flag == 1) {
					ret = read(fd, &key_value, sizeof(struct input_event));
					if( ret != sizeof(struct input_event)) {
						perror(" the file Ending!");
						return -1;
					}
					if(key_value.type == EV_KEY) {  //按照键值进行分支跳转,请根据实际情况修改
						if (key_value.value == 1) {  //按下时相应
							switch(key_value.code) {
								case ESC: {  //返回小图模式
									key_Return();
									break;
								}
								case HOME: {  //进入主程序
									key_Enter();
									break;
								}
								case POWER: {  //退出程序
									key_Back();
									flag = 0;
									break;
								}
								case ENTER: {  //打开选中的图片
									key_Open();
									break;
								}
								case UP: {  //上一页
									key_PageUp();
									break;
								}
								case DOWN: {  //下一页
									key_PageDown();
									break;
								}
								case LEFT: {  //上一张图片
									key_Up();
									break;
								}
								case RIGHT: {  //下一张图片
									key_Down();
									break;
								}
								default: {
									perror("Key Code Error!\n");
								}
							}
						}
					}
				}
				munmap(fb_mem, LENGTH * HEIGHT * 4);
			}
		}
		ret  = close(fd);
		if(ret < 0) {
			perror(" close ! ");
			return -1;	
		}
	}
	return 0;
}


电子音乐相册的相册部分,配合移植后的MoboPlayer可以实现音乐电子相册的功能。


你可能感兴趣的:(C/C++,Linux)