• TI IPNC Web网页之网页修改教程


    web网页程序修改

    打开gStudio之后,点击菜单栏中Help->Contents。先把这个诡异的编程语言看一遍吧。这里搬一些东西出来。

    GoDB简介

    从第一副图片中,我们可以看出,从源文件到可执行文件的过程。

    从第二幅图我们可以了解到GoDB是如何跨平台的。

    编程语言的话:

    GBasic is a variant of the Basic Language included in GoDB platform as the scripting language.

    这种编程语言大小写不区分,真是编程界的一朵奇葩。

    GBasic编程语言

    GBasic程序通常是有一个frm文件和与之名字相同的bas文件。比如说当HOME.frm被加载时,HOME.bas就会被执行。

    • GBasic中的字符串变量名以$结尾。
    • 如果没有$的变量则认为是数值变量
    • GBasic有两种对象(object),一种是Form Field Objects(可理解为Visual Studio中的rc文件),另外一种是数据库(专业版才能使用)
    • 在GBasic中调用From对象方式是用#对象名
    • GBasic中有三种变量范围,全局,局部和当前页面。
      其中变量名以开头的是全局变量,你可以在工程的任何地方访问这个变量。没有以开头的变量并且声明在Sub或者Function之外的,则为页面变量,声明在Sub或者Function内部的则是局部变量。
    • 像其它任何语言一样,GBasic也可以将针对多行代码进行封装。GBasic提供Subroutines和Functions这两种方式,前者没有返回值,后者需要返回值。如果要直接调用Subroutines,你需要在其前面家call,比如说call subname,而Functions的调用则不用。
    • Functions返回值的做法是赋值给函数名。

    GBasic自带了很多封装好的函数,这些函数如何用,请看Help。

    GStudio这个IDE像Visual Stduio一样,支持控件的事件触发(按钮按下,编辑框改变etc.)这些事件称之为控件的事件,还有另外一种事件叫做Global Event

    具体查看Help中的GBasic Reference->Global Event。这里稍微介绍下

    form_load当frm文件加载首先执行的是这个Sub。
    form_notify当收到服务器反馈时自动调用,此时在用GetMessage获取消息内容..
    form_timer,定时器触发时调用此Sub,通常使用settimer(1000)来使能定时触发。

    所以一般阅读GoDB工程代码一般先从每个bas文件的form_load开始看起。

    Debug

    • 在GUI的下拉菜单中,保证当前选中的是"DEBUG"模式;
    • 按F7编译工程,按F5会编译和启动项目;
    • 保证你在"Win32_Debug"文件夹中有"ip.txt"文件,这个是用于用户登录的。

    Release

    • Debug/ Release下拉菜单中选中Release
    • 在View-option在选项卡Build中在Make Read-Only BDB选中
    • 在文件夹Win32_Release中找到gIPNC-ro.bdb
    • 使用以下命令生成gIPNC-ro.gz

    gIPNC工程分析

    我们做的是在原有基础上添加东西,修修补补,谁要是有精力就从头开始弄吧。

    bas和frm和inc一一对应,bas为执行文件,inc为头文件,frm为form文件,相当于Visual Studio中的rc文件。

    还是先分析流程吧。

    首先当然是登录界面,那就是对应logon.bas和auth.bas,首次登录执行的auth.bas文件,而用户刷新过程中执行的logon.bas文件。

    关于logon.bas

    readprofile("PAGENAME",pageName$)
    ...
    readprofile("IPNC",loginDet$)
    ...
    

    首先读取变量名为IPNC和PAGENAME的profile,如果读取得到那么就将读取到的用户名和密码填充到用户名编辑框和登录编辑框(这就是记住密码功能),调用dwnldIniFile函数进行Http请求,请求内容是ip地址/ini.htm,这样如果认证通过,那么此时已经把所有关键字及其内容保存到~responseData$全局环境变量上。获取失败则弹出用户或密码错误。读取profile错误,则加载auth.frm。

    我们知道,TI IPNC除了用户验证登录之外还有区分用户权限,所以在成功调用dwnldIniFile调用getUserAuthority获取当前用户的权限,获取失败弹出错误信息,成功并且PAGENAME的值为LOGIN则加载auth.frm,否则直接进入liveVideo.frm

    温馨提示,仔细研究下writeprofile函数,你就知道如何做到真正的记住密码。

    温馨提示,GetIPAddress()是进行调试的关键。

    分析auth.bas不难发现,无非就是。先将读取到的IPNC变量的值进行填充,然后这个文件主要的逻辑就是cmdSubmit_Click这个按钮按下的事件处理函数了。先进行输入验证,然后是登录验证,也是调用dwnldIniFile进行认证getUserAuthority。最后成功加载livevideo.frm,并写PAGENAME的profile。

    ** 几个比较关键的文件 **

    这个工程里面有几个文件是比较重要(特殊的文件)的那就是leftmenu.bas,functions.inc,defines.inc,common.inckeywords.inc

    1. 其中leftmenu.bas是网页侧边栏的执行文件,添加,删除子菜单就修改这个文件。
    2. functions.inc里面定义了众多函数,大部分是网页keyword获取和设置的函数。
    3. defines.inc文件定义了一些关键数字,比如说侧栏菜单(主菜单,子菜单)多少个,比如关键字最多有多少个,有时候一些莫名其妙的错误就是由于这个文件上的数字没对上引起的。
    4. common.inc定义了一些通用函数,比如编辑框可以输入哪些字符,不可以输入哪些字符(CheckKey),产生Request Header(generateauthHeader)。
    5. keywords.inc,这个仅在functions.inc中被包括。这个文件其实不太重要,作用仅仅是用于显示获取或设置关键字时的错误信息而已。

    logon.bas和auth.bas他们都包括了functions.inc,defines.inc,common.inc。而其它的主页面除了这个三个文件之外,还包括leftmenu.bas,这样的效果就是将侧边栏和各个form的网页叠加起来。

    GBasic是从头到尾顺序执行的,所以每个bas文件先执行Sub或者functions之外的语句之后,然后再执行form_load事件,由于先包括了leftmenu.bas,所以会先执行leftmenu.bas里面的内容,而每个frm页面都包括了leftmenu.frm文件。这样就加载了侧边栏。

    leftmenu负责触发加载各个页面。

    添加删除侧边栏菜单

    这里只说怎么加,不讨论怎么建页面。

    打开leftmenu.bas

    dims ~menuArray$(MAXMAINMENU+MAXSUBMENU+3)
    dims menuOffImg$(MAXMAINMENU) = ("!camera_Off.bin","!users_Off.bin","!settings_Off.bin","!maintanance_off.bin","!support_off.bin")
    dims ~menuOnImg$(MAXMAINMENU) = ("!camera_On.bin","!users_On.bin","!settings_On.bin","!maintanance_on.bin","!support_on.bin")
    dims ~urlMainArray$(MAXMAINMENU) = ("!liveVideo.frm", "!addusers.frm","!videoImageSettings.frm","!maintenance.frm","!supportScreen.frm")
    dims ~urlSubArray$(MAXSUBMENU) = ("!videoImageSettings.frm","!videoAnalyticsSetting.frm","!DMVAeventMonitor.frm","!display_settings.frm", "!audioSetting.frm","!setDateTime.frm", "!NetworkSettings.frm", "!alarmSettings.frm", "!class.frm","!storageSetting.frm")
    
    dimi dmvaEnable
    
    #imgselected.hidden = 1	
    loadMenuCaptions()
    ....
    

    上面是我修改过的。其中比较关键的是几个宏定义的定义,如果你要修改,请算好侧边栏的个数,然后修改在defines.inc中的数值。bin文件是主菜单的对应的图片,关于图片后面才说,frm就是对应的页面啦,算好顺序...

    1. 如果要增加页面,则在leftmenu.frm中增加一个ReadOnly控件,然后NAME必须为rosubmenu,value为空,背景那些参照已有的..你会发现有好几个ReadOnly都叫做rosubmenu,然后这个ide就自动就其他们的name改为类似数组的样子..rosubmenu[0],而程序里面也是如此引用。
    2. 修改字符串数组~URLsUBaRRAY$,将建立好的FRM的文件名添加到末尾
    3. 修改子菜单数量maxsubmenu和leftmenuctrls(在DEFINE.INC中定义).各加1
    4. 修改子菜单名字,修改MENUcAPTIONS.LAN文件,这个文件前面5个是主菜单,后面是子菜单的名字
    5. BUG.将ARRmOUSEpOS(14, 4)改成ARRmOUSEpOS(maxmainmenu+maxsubmenu, 4),否则会出现数组越界
    6. 子菜单对应的页面的BAS文件必须包括两个函数savepage()和chkValueMismatch(),否则会报错..

    当然leftmenu大部分菜单鼠标点击时鼠标的触发事件,也就是加载相应的页面。当然还有什么图标排列,音视频开关等处理...

    另外值得注意的是:子菜单中有可能有一两个页面是默认隐藏的,某种条件触发下才显示。比如Live Video页面那个Example的下拉框就是一个触发条件,另外如果用户权限不同,子菜单显示的个数也有所不同,这些逻辑都在leftmenu.bas中。

    子页面流程分析

    IPNC网页默认几个页面,大部分都是传统的表单页面,无非就是些CheckBoxEditCommonBox之类的控件,加载页面的时候,就是获取服务器上对应的控件的值然后填充进去,保存页面的时候,则是发送http请求到web服务器进行保存然后重新获取更新。

    一般来说一个控件对应一个关键字。

    我们先从对应页面的form_load看起,然后看savepage,然后看各个控件触发事件..其它全局事件。

    我们拿声音设置页面为例,对应的文件是audiosetting.basaudiosetting.frm文件。

    Sub Form_Load
    	dimi retVal
    	retVal = loadIniValues()
    			
    	if ~maxPropIndex = 0 then 
    		msgbox("无法加载初始配置",0,"错误",3)
    		loadurl("!auth.frm")
    	endif
    	
    	call displayControls(LabelName$,XPos,YPos,Wdh,height)
    	call loadInitialValues()	
    	
    	showSubMenu(0,1)
    	setfocus("rosubmenu[4]")
    	selectSubMenu()	
    	setfocus("chkenableaudio")
    	call chkenableAudio_Click									'TR-19
    	
    	getimagefile(sliderImage$,"!slider_but.jpg")
    	#lblsuccessmessage$ = ""									'TR-35
    		
    End Sub
    

    retVal = loadIniValues()

    这是个关键函数,这个函数里面请求http://ip/ini.htm获取所有关键字的值,如果获取失败了,就提示错误。在loadIniValues函数中,有个字符串数组非常关键,每次添加新的关键字都必须修改这个字符串在后面添加新的关键字。keywords$

    网页在functions.inc中的loadIniValues()中解析得到这些值将这些属性和对应的放分别放到字符串数组~iniProperties$和iniPropValues$中.
    值得注意的是在放入~iniProperties$之前,在每个属性名之前加了字母"g".

    每个页面的form_load都会在一开始调用这个函数

    call loadInitialValues()

    这个函数,也是非常典型,几乎每个页面都会做类似的处理(可能函数名字不同或者没用函数),作用是获取当前页面关键字的值然后填充到控件里面。

    然后这里基本上都用到functions.inc中"get"开头的一些函数,这些函数参数不同,都是处理流程一致,都是分析~iniPropValues$这个全局变量然后取出对应的关键字的值。

    retVal = getAudioSetting(enableAudio,audioMode,inputVolume,_
    		encoding,sampleRate,bitRate, _
    		alarmLevel,outputVolume)
    
    'functions.inc中定义
    function getAudioSetting(byref dimi enableAudio, byref dimi audioMode, byref dimi inputVolume, _
    						 byref dimi encoding, byref dimi sampleRate, byref dimi bitRate, _
    						 byref dimi alarmLevel, byref dimi outputVolume)
    	'TR-26					 
    	dims varName$(8)  = ("enableAudio","audioMode","inputVolume", _
    						  "encoding","sampleRate","bitRate", _
    						  "alarmLevel","outputVolume") 
    
    						  
    	dims propName$(8) = ("gaudioenable","gaudiomode","gaudioinvolume", _
    						 "gencoding","gsamplerate","gaudiobitrate", _
    						 "galarmlevel","gaudiooutvolume")
    		
    	dims tempVal$(8)
    	dimi i,retVal
    	
    	retVal = getiniValues(propName$,tempVal$)	
    	
    	if retVal = 0 then
    			
    		for i= 0 to ubound(tempVal$)	
    			
    			{varName$(i)} = strtoint(tempVal$(i))		
    			
    		next
    		
    	endif
    	
    	return retVal	
    	
    End Function
    

    所以当你添加新的关键字时,做法可以是在原有函数基础增加参数。也可以按照里面的这些函数的形式和逻辑重新定义一个新的函数...

    下面介绍另外一个重要函数,那就是savepage函数,记住不管你页面是否需要保存,都必须存在这个函数。正如前面一小节所说......

    savepage函数里面重要是使用functions.inc中"set"开头的一些函数。这些函数参数不尽相同,但是逻辑相同,都是通过发送http请求设置关键字的值。

    savepage函数一般还会做控件输入值有效的检测,错误成功信息显示等处理...

    /*一般实在保存按钮的事件响应函数中调用savepage函数*/
    Sub cmdsave_Click	
    	if canReload = 1 then
    		savePage()		
    	end if
    End Sub
    
    Sub savePage()
    	'Validate user input controls values
    	iff validatemodecontrols() = 0 then return	
    		
    	dimi retVal,i
    	' TR-26 set values to camera
    	retVal = setAudioSetting(#chkenableaudio,#drpaudiomode,atol(#sldaudioinput$),_
    							 #drpencoding,#drpsamplerate,#drpbitrate,_
    							 #sldalarmlevel,atol(#sldaudiooutput$))
    	
    
    	saveSuccess = retVal
    	tempX = #lblsuccessmessage.x
    	'Based on reload flag wait for the camera to restart
    	if getReloadFlag() = 1 then								'TR-45				
    		#lblsuccessmessage.style = 128
    		#lblsuccessmessage.x = #lblsuccessmessage.x + #lblsuccessmessage.w/3
    		canReload = 0
    		animateCount = 1
    		call animateLabel("lblsuccessmessage","参数更新中")
    	else // If Reload animation is not required
    		canReload = 1
    	end if
    	
    	if canReload = 1 Then	//Do the remaining actions after reload animation is done
    		call displaySaveStatus(saveSuccess)		
    	end if	
    End Sub
    
    function setAudioSetting(dimi enableAudio, dimi audioMode, dimi inputVolume, _
    						 dimi encoding, dimi sampleRate, dimi bitRate, _
    						 dimi alarmLevel, dimi outputVolume)	
    	dimi ret
    	dims value$
    	dims responseData$
    	' TR-26
    	value$ = "audioenable="+enableAudio+"&audiomode="+audioMode+"&audioinvolume="+inputVolume+_
    			 "&encoding="+encoding+"&samplerate="+sampleRate+"&audiobitrate="+bitRate+_
    			 "&alarmlevel="+alarmLevel+"&audiooutvolume="+outputVolume
    	pprint value$		 
    	ret = setProperties(value$, responseData$)	
    	
    	if ret > 0 then
    		
    		dims propName$(8) = ("gaudioenable","gaudiomode","gaudioinvolume", _
    							 "gencoding","gsamplerate","gaudiobitrate", _
    							 "galarmlevel","gaudiooutvolume")
    		dims propVal$(8)
    		
    		propVal$(0) = enableAudio
    		propVal$(1) = audioMode
    		propVal$(2) = inputVolume
    		propVal$(3) = encoding
    		propVal$(4) = sampleRate
    		propVal$(5) = bitRate
    		propVal$(6) = alarmLevel
    		propVal$(7) = outputVolume
    		
    		~errorKeywords$ = ""
    		~errorKeywords$ =  chkRetStatusAndUpdate$(responseData$,propName$,propVal$)
    		
    		if len(~errorKeywords$) > 0 then
    			return -10
    		else
    			return ret
    		endif		
    		
    	endif 
    	
    	return ret				
    						
    End Function
    

    跟踪到里面去,不难发现,实际上就是发送这样形式的Http请求:

    vb.htm?keyword1=xx&keyword2=xxx

    当增加新的关键字时,可以仿照这些set开头函数重新定义一个新的函数,也可以在原有基础上扩充。

    GoDB端添加关键字的流程

    这里介绍在GoDB端添加关键字的流程。我们忽略boa端代码的修改,所以修改完之后,既不能获取到这个关键字也无法设置成功。

    现在举添加rtmp功能的例子..

    页面如下,在网络/端口设置页面添加一个checkbox和一个edit,这就对应了两个关键字,关键字名字分别为rtmp_enrtmp_url(随意)

    还是从from_load开始,还是从加载控件默认值的函数开始...

    call ShowDefaultValues()

    在这个Sub内:
    dimi rtmp_en
    Dims rtmp_url$

    然后我们选择扩充已有的函数

    retVal=getSNTPRTSPDetails(sntpServer$, multiCast,rtmp_en,rtmp_url$)

    /*在functions.inc中定义*/
    function getSNTPRTSPDetails(byref dims sntpServer$,byref dimi multiCast,byref dimi rtmp_en,byref dims rtmp_url$)
    	
    	dims varName$(4)  = ("sntpServer$","multiCast","rtmp_en","rtmp_url$")
    	dims propName$(4) = ("gsntpip","gmulticast","grtmp_en","grtmp_url")
    	dims tempVal$(4)
    	dimi i,ret
    	ret=getiniValues(propName$,tempVal$)
    		
    	if ret>=0 then
    		for i= 0 to ubound(tempVal$)
    			if i=1 or i=2 then
    				{varName$(i)} = strtoint(tempVal$(i))			
    			else 
    				{varName$(i)} = tempVal$(i)				
    			endif
    			
    		next
    	endif
    	return ret 
    	
    End Function
    

    你对比下原始函数就知道我修改了哪里..

    接着我们修改functions.inc中的loadIniValues函数,将rtmp_enrtmp_url添加到keywords$字符串后面

    /*....*/
    	keywords$ +=",aviformat,aviformatname,aviduration,avidurationname,reloadtime,qpinit1,qpinit2,qpinit3"_
    				",videocodeccombo,videocodeccomboname,streamname1,streamname2,streamname3"_
    				",localdisplayname,sdinsert,reloadflag,dmvaenable,minnamelen,maxnamelen,minpwdlen,maxpwdlen,maxaccount"_
    				",bkupfirmware,display_mode,ppt_sw_en,ppt_sw_sensitivity,ppt_sw_interval_time,channel_id,psname,piname,ch_id_name"_
    				",file_size,video_long,brightness2,contrast2,saturation2,sharpness2,brightness3,contrast3,saturation3,sharpness3,brightness4,contrast4,saturation4,sharpness4"_
    				",language,ftp_upload_option,ftp_upload_time,trackip,cloudip,serverenable,singlecodecres,rtmp_en,rtmp_url"
    

    接着我们修改keywords.inc文件,将这两个关键字添加到cameraKeywords$关键字后面。"|"右面是错误提示信息,合理填写即可。

    cameraKeywords$ += ",display_mode|Display mode,ppt_sw_en|PPT Switch Enable,ppt_sw_interval_time|PPT Switch interval Time,"_
    				   ",ppt_sw_sensitivity|PPT Switch sensitivity,channel_id|main display channel,language|language,trackip|track ip,cloudip|cloudip,"_
    				   ",serverenable|Upload to server,singlecodecres|resolution for single stream,rtmp_en|rtmp enable,rtmp_url|rtmp url"
    

    接着,我们修改savepage函数。

    retVal = setSNTPRTSPDetails(#txtsntpserver$, #chkrtspmulticast,#chkrtmp,#txtrtmpurl$)

    这里传入的参数是直接将对象的值传入..

    function setSNTPRTSPDetails(dims sntpServer$,dimi multiCast,dimi rtmp_en,dims rtmp_url$)
    	dimi ret
    	dims SNTPRTSPDetails$
    	dims responseData$
    	
    	SNTPRTSPDetails$="sntpip="+sntpServer$+"&multicast="+multiCast+"&rtmp_en="+rtmp_en+"&rtmp_url="+rtmp_url$		
    					
    	ret = setProperties(SNTPRTSPDetails$, responseData$)
    	
    	if ret >= 0 then
    	
    		dims propName$(4) = ("gsntpip","gmulticast","grtmp_en","grtmp_url")
    
    		dims propVal$(4)
    		propVal$(0) = sntpServer$
    		propVal$(1) = multiCast		
    		propVal$(2) = rtmp_en
    		propVal$(3) = rtmp_url$
    		
    		~errorKeywords$ = ""
    		~errorKeywords$ =  chkRetStatusAndUpdate$(responseData$,propName$,propVal$)
    		
    		if len(~errorKeywords$) > 0 then
    			return -10
    		else
    			return ret
    		endif		
    		
    	endif 
    	
    	return ret			
    	
    End Function
    

    这样着,关键字添加完毕了,按照前面文章说的步骤编译生成吧..

    boa端添加关键字的流程

    只讲怎么添加。

    请自行用工具定位下面变量,函数的位置。

    先从SysInfo结构体开始修改,这个结构体将保存所有网页表单,关键字的值。

    我们在末尾添加

    typedef struct SysInfo{
    	//....
    	__u8 rtmp_enable; ///< rtmp_enable
        char rtmp_url[MAX_RTMP_URL_LEN+1];
    }SysInfo;
    

    网页需要出厂默认值,所以在修改system_default.h文件添加两个宏定义。

    #define RTMP_EANABLE_DEFAULT 0 //RTMP使能,0为不使能...
    #define RTMP_URL_DEFAULT  "rtmp://192.168.1.120:1935/live/xxoo"
    

    修改file_mng.c
    修改全局静态结构体SysInfoDefault,往末尾添加

    static SysInfo SysInfoDefault =
    {
    	//....
    	RTMP_EANABLE_DEFAULT,
    	RTMP_URL_DEFAULT
    };
    

    修改HttpOptionTable结构体。

    HTTP_OPTION HttpOptionTable [] =
    {
    	//....
    	{ "rtmp_en"			, set_rtmp_en				, AUTHORITY_OPERATOR, FALSE,  TRUE, NULL },
    	{ "rtmp_url"				, set_rtmp_url					, AUTHORITY_OPERATOR, FALSE,  TRUE, NULL },
    	//...
    }
    

    接着在该表所在文件定义这两个函数,一个是整数,一个字符串,注意区别。

    void set_rtmp_en(request *req, COMMAND_ARGUMENT *argm)
    {
    	__u8 value = atoi(argm->value);
    
    	do {
    		ControlSystemData(SFIELD_SET_RTMP_EN, (void *)&value, sizeof(value));
    		req->buffer_end += sprintf(req_bufptr(req), OPTION_OK "%s
    ", argm->name);
    		return;
    	} while (0);
    	req->buffer_end += sprintf(req_bufptr(req), OPTION_NG "%s
    ", argm->name);
    }
    
    void set_rtmp_url(request *req, COMMAND_ARGUMENT *argm)
    {
    	do {
    		if(ControlSystemData(SFIELD_SET_RTMP_URL, (void*)argm->value, strlen(argm->value)) < 0)
    			break;
    		req->buffer_end += sprintf(req_bufptr(req), OPTION_OK "%s
    ", argm->name);
    		return;
    	} while (0);
    	req->buffer_end += sprintf(req_bufptr(req), OPTION_NG "%s
    ", argm->name);
    }
    

    sysctrl.h定义SFIELD_SET_RTMP_EN和SFIELD_SET_RTMP_URL

    ControlSystemData函数中添加

    		case SFIELD_SET_RTMP_URL:
    			ret = SetSysCommon(data, len,SYS_MSG_SET_RTMP_URL);
    			break;
    
    		case SFIELD_SET_RTMP_EN:
    			ret = SetSysCommon(data, len, SYS_MSG_SET_RTMP_EN);
    			break;
    

    Msg_Def.h中定义SYS_MSG_SET_RTMP_URLSYS_MSG_SET_RTMP_EN

    ProcSysMsg函数添加

    		case SYS_MSG_SET_RTMP_EN:
    		{
    			unsigned char value;
    			DBG("SYS_MSG_SET_RTMP_EN
    ");
    			if(pMsg->length != sizeof(value))
    				break;
    			ShareMemRead(pMsg->offset, &value, pMsg->length);
    			if(SetRtmpEn(value) != 0){
    				printf("
    SystemServer:Fail at SYS_MSG_SET_MULTICAST
    ");
    				break;
    			}
    			ret = 1;
    			break;
    		}
    
    		case SYS_MSG_SET_RTMP_URL:
    		{
    			if(pMsg->length > SYSTEM_SERVER_BUFFER_LENGTH){
    				printf("String length bigger then System Server Buffer
    ");
    				break;
    			}
    			ShareMemRead(pMsg->offset, buffer, pMsg->length);
    			if(SetRtmpUrl(buffer, pMsg->length) != 0){
    				printf("Fail at SYS_MSG_SET_RTMP_URL
    ");
    				break;
    			}
    			ret = 1;
    			break;
    		}
    

    定义SetRtmpUrlSetRtmpEn函数(这里在system_control.c中定义)

    这两个函数的内容就非常自由了,不过和其它相同的地方就是就是需要将关键字保存到sysenv.cfg文件中。

    所以分别各自定义一个函数用于保存关键字。

    fSetRtmpEnfSetRtmpUrl(file_msg_drv.c)中定义。

    int fSetRtmpEn(unsigned char value)
    {
    	SysInfo *pSysInfo = (SysInfo *)pShareMem;
    	if(pSysInfo == NULL)
    		return -1;
    	if (value == pSysInfo->rtmp_enable)
    		return 0;
    	memcpy(&pSysInfo->rtmp_enable, &value, sizeof(value));
    	return SetSysInfo(0);
    }
    int fSetRtmpUrl(void *buf, int len)
    {
    	SysInfo *pSysInfo = (SysInfo *)pShareMem;
    	if(pSysInfo == NULL)
    		return -1;
    	if(sizeof(pSysInfo->rtmp_url) < len + 1)
    		return -1;
    	memcpy(&pSysInfo->rtmp_url, (char*)buf, len);
    	pSysInfo->rtmp_url[len] = '';
    	return SetSysInfo(0);
    }
    
    
    int SetRtmpEn(unsigned char value)
    {
    	int ret = 0;
    	SysInfo *pSysInfo = GetSysInfo();
    	if(pSysInfo == NULL)
    		return -1;
    	if(value != pSysInfo->rtmp_enable)
        {
            ret = fSetRtmpEn(value);
            if ( value == 1 )
                rtmp_start();
            else
                rtmp_stop();
    
        }
    	return ret;
    }
    
    
    int SetRtmpUrl(void * buf, int length)
    {
        int ret = 0;
        signed char* serverip=(signed char*)buf;
    	SysInfo *pSysInfo = GetSysInfo();
    	if(pSysInfo == NULL)
    		return -1;
        if(strncmp(serverip,pSysInfo->rtmp_url,length) != 0)
        {
            ret = fSetRtmpUrl(buf,length);
            rtmp_stop();
            if ( pSysInfo->rtmp_enable )
                rtmp_start();
        }
        return ret;
    }
    

    修改HttpArgument结构体,用于获取关键字的值

    HTML_ARGUMENT HttpArgument [] =
    {
    	//...
    	{ "rtmp_en"		, para_rtmp_en  			, AUTHORITY_VIEWER , NULL },
    	{ "rtmp_url"			, 	para_rtmp_url		, AUTHORITY_VIEWER , NULL },
    	//...
    };
    
    
    int para_rtmp_en(char *data, char *arg)
    {
      SysInfo* pSysInfo = GetSysInfo();
    	if(pSysInfo == NULL)
    		return -1;
    	return sprintf(data, "%d", pSysInfo->rtmp_enable);
    }
    
    int para_rtmp_url(char *data, char *arg)
    {
        SysInfo* pSysInfo = GetSysInfo();
    
    	if(pSysInfo == NULL)
    		return -1;
    	return sprintf(data, "%s", pSysInfo->rtmp_url);
    }
    

    以上就成功的加入了关键字了,在其它线程里面,你只需要调用

        SysInfo *pSysInfo = GetSysInfo();
    	//pSysInfo->rtmp_en
    	//pSysInfo->rtmp_url
    
  • 相关阅读:
    Hadoop Mapreduce分区、分组、二次排序过程详解
    hadoop的NullWritable
    CentOS7.0修改主机名(hostname)
    Linux下不重启永久修改hostname
    稀缺——我们是如何陷入贫穷与忙碌的
    slf4j log4j logback关系详解和相关用法
    使用logstash+elasticsearch+kibana快速搭建日志平台
    安装XAMPP时出现 unable to realloc 83886080 bytes
    ElasticSearch查询max_result_window问题处理
    后台CMS日志处理记录
  • 原文地址:https://www.cnblogs.com/tracyone/p/4431698.html
Copyright © 2020-2023  润新知