当前位置:   article > 正文

数码相框实现四:实现图片的连播模式_移动设备开发数码相框设计

移动设备开发数码相框设计

一、目标与思路
有了前面浏览页面的显示和功能实现,“连播模式”就可完成了。
本文目标:实现图片的连播
-->连播模式:如果没有设置,则默认从根目录/递归显示所有的图片(bmp和jpg格式)。
	否则,如果设置了播放的“时间间隔”  和 选择的“播放目录”,
	就会按设置的时间间隔递归连续显示那个目录下的所有图片。

如果实现呢?
我画了张连播页面的Run() 函数执行流程图,如下所示
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

下面根据这个流程图搭建整体实现,然后细讲每一方面的实现。
  • 1
二、源码实现与效果图
脑海中一定要先理清上面流程图,然后看下面整体实现的搭建。
  • 1
2.1 整体实现的搭建
/* 当点击主页面的“连播模式时”,主线程执行下面函数 */
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;
}	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
框架就是上面那样,下面按顺序介绍每一步如何实现。
补充解释:
PrepareNextPicture(1)
PrepareNextPicture(0)  的区别?
0:以子线程的身份去获得显存的缓冲块,不一定获得成功。即返回的ptVideoMem 可能为NULL
1:当时间到时,如果ptVideoMem 还没准备好,就要以主线程身份去获得显存的缓冲块了,这一操作
     肯定成功,因为迫在眉睫要显示下一张图片了呀!
另外:Hookup 是“连播”的意思。而韦老师选取的是“Auto”,两者都可以,我喜欢前者。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
2.2 获得时间间隔和播放目录
1)GetPageCfg()函数,获得时间间隔和播放目录。实现如下
  • 1

在这里插入图片描述

2.3 准备下一张图片
2)PrepareNextPicture() 函数,返回ptVideoMem,即指向已设置好显示下一张图片的缓冲块起始地址。
	该函数的逻辑图看第一张图,下面列出该函数主体,并解释每一语句的作用。
  • 1
  • 2

准备下一张图片
获得下一个显示的图片名
递归获得目录的文件名

2.4 递归获得目录下文件名
这部分代码很关键,所以一定要贴出来,如下
  • 1
/* 以深度优先的方式获得目录下的文件 
 * 即: 先获得顶层目录下的文件, 再进入一级子目录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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
2.5 效果图展示
备注:完整源码可到我的一篇“代码集合”博文获取百度网盘链接
OK,最后来看下效果图
  • 1
  • 2

图片连播效果图1
图片连播效果图2

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/263426
推荐阅读
相关标签
  

闽ICP备14008679号