赞
踩
有了前面浏览页面的显示和功能实现,“连播模式”就可完成了。
本文目标:实现图片的连播
-->连播模式:如果没有设置,则默认从根目录/递归显示所有的图片(bmp和jpg格式)。
否则,如果设置了播放的“时间间隔” 和 选择的“播放目录”,
就会按设置的时间间隔递归连续显示那个目录下的所有图片。
如果实现呢?
我画了张连播页面的Run() 函数执行流程图,如下所示
下面根据这个流程图搭建整体实现,然后细讲每一方面的实现。
脑海中一定要先理清上面流程图,然后看下面整体实现的搭建。
/* 当点击主页面的“连播模式时”,主线程执行下面函数 */ static int g_iExitAutoPlay = 0; /* 是否退出子线程自动播放的标志位,默认肯定“否” */ static void HookupPageRun(void) { /* 别忘了这步!确保能重复播放 */ /* 因为是全局静态变量,初始化一次,程序结束才销毁 */ g_iExitAutoPlay = 0; /* 1. 获得时间间隔和播放目录*/ GetPageCfg(&g_tPageCfg); /* 2. 启动一个线程来连续显示图片 */ pthread_create(&g_tHookupPageThreadID, NULL, AutoPlayThreadFunction, NULL); while(1) { /* 3. 等待触摸屏输入(主线程会休眠,有输入事件时,子线程会唤醒主线程) */ iRet = GetInputEvent(&tInputEvent); if(iRet == 0)// 捕捉到触摸屏点击事件,返回0 { /* 4. 唤醒后改变标志位让子线程退出播放 */ /* 因为标志位是线程共享的,修改时需加互斥锁 */ pthread_mutex_lock(&g_tAutoPlayThreadMutex); g_iExitAutoPlay = 1; pthread_mutex_unlock(&g_tAutoPlayThreadMutex); /* 等待子线程退出,确保释放资源 */ pthread_join(g_tHookupPageThreadID,&thRet); return; } } } /* 下面的子线程函数,实现按设定的时间间隔连续播放选定目录(或默认根目录)下的图片 */ static void* AutoPlayThreadFunction(void* pVoid) { int bExit; int bFirst = 1; while(1) { /* 1.获得互斥锁,并判断是否要退出播放 */ pthread_mutex_lock(&g_tAutoPlayThreadMutex); bExit = g_iExitAutoPlay; pthread_mutex_unlock(&g_tAutoPlayThreadMutex); if(bExit) break; /* 2. 准备要显示的图片 */ ptVideoMem = PrepareNextPicture(0); /* 3. 时间到了就显示出来 */ f(!bFirst) { sleep(g_tPageCfg.iIntervalSecond); /* 先用休眠来代替 */ } bFirst = 0; if(ptVideoMem == NULL) { /* 无论如何,肯定会准备好下一页面 */ ptVideoMem = PrepareNextPicture(1); } /* 4. 刷到设备上去并释放显存 */ FlushVideoMemToDev(ptVideoMem); PutVideoMem(ptVideoMem); } return NULL; }
框架就是上面那样,下面按顺序介绍每一步如何实现。
补充解释:
PrepareNextPicture(1)
PrepareNextPicture(0) 的区别?
0:以子线程的身份去获得显存的缓冲块,不一定获得成功。即返回的ptVideoMem 可能为NULL
1:当时间到时,如果ptVideoMem 还没准备好,就要以主线程身份去获得显存的缓冲块了,这一操作
肯定成功,因为迫在眉睫要显示下一张图片了呀!
另外:Hookup 是“连播”的意思。而韦老师选取的是“Auto”,两者都可以,我喜欢前者。
1)GetPageCfg()函数,获得时间间隔和播放目录。实现如下
2)PrepareNextPicture() 函数,返回ptVideoMem,即指向已设置好显示下一张图片的缓冲块起始地址。
该函数的逻辑图看第一张图,下面列出该函数主体,并解释每一语句的作用。
这部分代码很关键,所以一定要贴出来,如下
/* 以深度优先的方式获得目录下的文件 * 即: 先获得顶层目录下的文件, 再进入一级子目录A * 先获得一级子目录A下的文件, 再进入二级子目录AA, ... * 处理完一级子目录A后, 再进入一级子目录B * * "连播模式"下调用该函数获得要显示的文件 * 有两种方法获得这些文件: * 1. 事先只需要调用一次函数,把所有文件的名字保存到某个缓冲区中 * 2. 要使用文件时再调用函数,只保存当前要使用的文件的名字 * 第1种方法比较简单,但是当文件很多时有可能导致内存不足. * 我们使用第2种方法: * 假设某目录(包括所有子目录)下所有的文件都给它编一个号 * piStartNumberToRecord : 从第几个文件开始取出它们的名字 * piCurFileNumber : 本次函数执行时读到的第1个文件的编号 * piFileCountHaveGet : 已经得到了多少个文件的名字 * iFileCountTotal : 总共要取出多少个文件的名字 * */ int GetFilesIndir(char *strDirName, int *piStartNumberToRecord, int *piCurFileNumber, int *piFileCountHaveGet, int iFileCountTotal, char apstrFileNames[][256]) { int iError; PT_DirContent *aptDirContents; int iDirContentsNumber; int i; char strSubDirName[256]; #define MAX_DIR_DEEPNESS 10 static int iDirDeepness = 0; /*注意:静态局部变量,只初始化一次!*/ if(iDirDeepness > MAX_DIR_DEEPNESS) //递归终止的条件 { return -1; } iDirDeepness++; iError = GetDirContents(strDirName, &aptDirContents, &iDirContentsNumber); if(iError) { DBG_PRINTF("GetDirContents error!\n"); iDirDeepness--; return -1; } /* 先记录文件 */ for(i = 0; i < iDirContentsNumber; ++i) { if(aptDirContents[i]->eFileType == FILETYPE_FILE) { if(*piCurFileNumber >= *piStartNumberToRecord) { snprintf(apstrFileNames[*piFileCountHaveGet], 256, "%s/%s", strDirName, aptDirContents[i]->strName); (*piFileCountHaveGet)++; (*piCurFileNumber)++; (*piStartNumberToRecord)++; if(*piFileCountHaveGet >= iFileCountTotal) { FreeDirContents(aptDirContents, iDirContentsNumber); iDirDeepness--; return 0; } } else { (*piCurFileNumber)++; } } } /* 递归处理目录 */ for(i = 0; i < iDirContentsNumber; ++i) { if((aptDirContents[i]->eFileType == FILETYPE_DIR) && isRegDir(strDirName, aptDirContents[i]->strName)) { snprintf(strSubDirName, 256, "%s/%s", strDirName, aptDirContents[i]->strName); GetFilesIndir(strSubDirName, piStartNumberToRecord, piCurFileNumber, piFileCountHaveGet, iFileCountTotal, apstrFileNames); if(*piFileCountHaveGet >= iFileCountTotal) { FreeDirContents(aptDirContents, iDirContentsNumber); iDirDeepness--; return 0; } } } FreeDirContents(aptDirContents, iDirContentsNumber); iDirDeepness--; return 0; }
备注:完整源码可到我的一篇“代码集合”博文获取百度网盘链接
OK,最后来看下效果图
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。