⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 learndlg.cpp

📁 WinLIRC软件:WinLIRC是一个以 LIRC为基础而在Windows环境发展出来的模块, 而什么是LIRC呢...它其实是 Linux InfraredRemote Control的缩写, 本
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* 
 * This file is part of the WinLIRC package, which was derived from
 * LIRC (Linux Infrared Remote Control) 0.5.4pre9.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Copyright (C) 1998,99 Christoph Bartelmus <columbus@hit.handshake.de>
 * Copyright (C) 1999 Jim Paris <jim@jtan.com>
 */

#include "stdafx.h"
#include "winlirc.h"
#include "learndlg.h"
#include <sys/types.h>
#include <string.h>
#include "dumpcfg.h"
#include "config.h"
#include "remote.h"

#ifndef min
#define min(a,b) (a>b ? b:a)
#endif
#ifndef max
#define max(a,b) (a>b ? a:b)
#endif

unsigned int LearnThread(void *dlg) {((Clearndlg *)dlg)->LearnThreadProc();return 0;}
unsigned int AnalyzeThread(void *dlg) {((Clearndlg *)dlg)->AnalyzeThreadProc();return 0;}
unsigned int RawThread(void *dlg) {((Clearndlg *)dlg)->RawThreadProc();return 0;}


/////////////////////////////////////////////////////////////////////////////
// Clearndlg dialog


Clearndlg::Clearndlg(CIRDriver *ndrv, const char *nfilename, 
					 lm nlearn_mode, CWnd* pParent /*=NULL*/)
	: CDialog(Clearndlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(Clearndlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT

	drv=ndrv;
	filename=nfilename;
	learn_mode=nlearn_mode;
	fout=NULL;

	::learn_dialog=this;
}

Clearndlg::~Clearndlg()
{
	KillThread(&LearnThreadHandle,&LearnThreadEvent);
	if(fout!=NULL) { fclose(fout); fout=NULL; }
	if(GotInput) { CloseHandle(GotInput); GotInput=NULL; }
}

void Clearndlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(Clearndlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(Clearndlg, CDialog)
	//{{AFX_MSG_MAP(Clearndlg)
	ON_BN_CLICKED(IDC_BUTTON1, OnEnter)
	ON_WM_CLOSE()
	ON_BN_CLICKED(IDC_ENTER, OnEnter)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// Clearndlg message handlers

BOOL Clearndlg::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	((CEdit *)GetDlgItem(IDC_OUT))->SetLimitText(0xFFFF);

	char *mode=(learn_mode==lm_learn)?"w":"r";
	
	if((fout=fopen(filename,mode))==NULL)
	{
		MessageBox("Could not open configuration file.");
		EndDialog2(IDCANCEL);
	}

	if((GotInput=CreateEvent(NULL,FALSE,FALSE,NULL))==NULL)
	{
		MessageBox("Could not create event.");
		EndDialog2(IDCANCEL);
	}

	/* THREAD_PRIORITY_IDLE combined with the REALTIME_PRIORITY_CLASS */
	/* of this program still results in a really high priority. (16 out of 31) */
	
	AFX_THREADPROC tp;
	switch(learn_mode)
	{
	case lm_learn:		tp=LearnThread; break;
	case lm_analyze:	tp=AnalyzeThread; break;
	case lm_raw:		tp=RawThread; break;
	}
	if((LearnThreadHandle=AfxBeginThread(tp,
		(void *)this,THREAD_PRIORITY_IDLE))==NULL)
	{
		CloseHandle(GotInput); GotInput=NULL;
		MessageBox("Could not initialize thread.");
		EndDialog2(IDCANCEL);
	}	
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void Clearndlg::output(const char *s, bool replacelast)
{
	CEdit *out=(CEdit *)GetDlgItem(IDC_OUT);
	if (out==NULL) return;
	if(s==NULL)
	{
		/* clear output */
		out->SetSel(0,-1);
		out->ReplaceSel("");
		return;
	}

	/* limit it to 120 characters, then add \r\n (if not replacing current line) */
	/* we don't add \r\n if replacing current line because that causes the box to */
	/* scroll up and down real quick when the last line is deleted and removed. */
	char t[256];
	_snprintf(t,120,"%s",s);
	t[120]=0;
	
	if(replacelast && out->GetLineCount()>1)
	{
		out->SetSel(out->LineIndex(out->GetLineCount()-2),out->GetWindowTextLength()-2);
	}
	else
	{
		strcat(t,"\r\n");
		out->SetSel(out->GetWindowTextLength(),out->GetWindowTextLength());
	}
	out->ReplaceSel(t);

	if(out->GetLineCount()>500)
	{
		/* start clearing out lines to avoid hitting the 64k limit */
		/* (122 * 500 = 61000) */
                out->SetSel(0,out->LineIndex(100),TRUE);
		out->ReplaceSel("");
	}
	out->SetSel(out->GetWindowTextLength(),out->GetWindowTextLength());
}

void Clearndlg::input(const char *prompt, char *s, int maxlen, bool allowempty)
{
	CEdit *in=(CEdit *)GetDlgItem(IDC_IN);
	CButton *ent=(CButton *)GetDlgItem(IDC_ENTER);

	ent->EnableWindow(true);
	in->SetSel(0,-1);
	in->ReplaceSel("");
	in->SetLimitText(maxlen);
	this->GotoDlgCtrl(in);
	
	int len;
	HANDLE events[2]={GotInput,LearnThreadEvent};
	do {
		output(prompt);
		ResetEvent(GotInput);
		int res=WaitForMultipleObjects(2,events,FALSE,INFINITE);
		if(res==(WAIT_OBJECT_0+1))
		{
			DEBUG("LearnThread terminating\n");
			AfxEndThread(0);
			return;
		}
		len=in->GetWindowTextLength();
	} while((!allowempty && len==0));
	s[len]=0;
	
	ent->EnableWindow(false);
	in->GetWindowText(s,maxlen);
	in->SetSel(0,-1);
	in->ReplaceSel("");
	in->SetLimitText(maxlen);
}

void Clearndlg::OnClose() 
{
	DEBUG("Killing LearnThread\n");
	KillThread(&LearnThreadHandle,&LearnThreadEvent);
	DEBUG("Closing GotInput event\n");
	if(GotInput) { CloseHandle(GotInput); GotInput=NULL; }
	DEBUG("Closing fout\n");
	if(fout!=NULL) fclose(fout); fout=NULL;
	DEBUG("Calling CDialog::OnClose()\n");
	CDialog::OnClose();
}

void Clearndlg::OnEnter() 
{
	SetEvent(GotInput);
}

bool Clearndlg::GetGap(unsigned long &gap,
					   unsigned long &count,
					   unsigned long &repeat_gap,
					   unsigned long *repeat)
{
	unsigned long data, average, signalcount;
	int mode;

	signalcount=average=mode=0;
	while(drv->readdata(250*1000,LearnThreadEvent)!=0)
		; /* wait for signals to stop coming for at least 0.25 sec */
	
	for(;;)
	{
		data=drv->readdata(30*1000*1000,LearnThreadEvent);

		if(data==0) return false;
		if(signalcount>MAX_SIGNALS) return false;

		if(is_space(data) && mode==0)
		{
			if(average==0)
			{
				if(data>100000) continue;
				average=data;
			}
			else
			{
				if(data>10*average ||
					(signalcount>10 && data>5*average))
				{
					count=signalcount;
					signalcount=0;
					gap=data;
					mode=1;
					continue;
				}
				average = (average*signalcount + data)/(signalcount+1);
			}
		}
		/* found gap, getting repeat code */
		if(mode==1)
		{
			if(signalcount<3) repeat[signalcount]=data&(PULSE_BIT-1);
			else 
			{
				if(data < (gap - gap*remote.eps/100))
				{
					/* if value is less than current gap, 
				    then it's probably not a repeat gap */
					DEBUG("repeat not detected, data=%d gap=%d\n",data,gap);
					repeat[0]=repeat[1]=repeat[2]=0;
				}
				else
				{
					/* otherwise, we'll assume it is */
					DEBUG("repeat detected, repeat_gap=%d\n",data);
					repeat_gap=data;
				}
				break;
			}
		}
		signalcount++;
	}
	return true;
}

void Clearndlg::DoGetGap(void)
{
	output("Step One: Determine signal gap, signal length, and repeat codes.");
	output("----------------------------------------------------------------"
		   "----------------------------------------------------------------");
	output("");
	output("You will be asked to press an arbitrary button a number of times.");
	output("Please hold it in for at least one second each time, and wait at");
	output("least one second between keypresses.");
	output("");
	output("If you want to manually enter a signal gap and signal length, you");
	output("may do so now (ie, \"31000 52\").  Otherwise, just hit ENTER.");

	/* First, read it until we get two results in a row that are pretty close. */
	int fault=0;
	unsigned long last_gap=0;
	unsigned long last_count=0;
	unsigned long last_repeat_gap=0;
	unsigned long last_repeat[3]={0,0,0};
	unsigned long gap, count, repeat_gap, repeat[3];
	int i;
	bool manualdata=false;
	char s[1024];

	
	input("Gap and length?",s,1024,true);
	if(strlen(s)!=0 && sscanf(s,"%ld %ld",&gap,&count)==2) manualdata=true;

	if(manualdata)
	{
		DEBUG("manual data entered, gap=%ld count=%ld\n",gap,count);
		code.length=count;
		remote.gap=gap;
		remote.repeat_gap=0;
		remote.prepeat=0;
		remote.srepeat=0;
		remote.ptrail=0;

		fprint_comment(fout,&remote);
		fprint_remote_head(fout,&remote);
		fprint_remote_signal_head(fout,&remote);
		return;
	}

	output("Press a button.");
	bool match=false;
	while(!match)
	{
		if(GetGap(gap,count,repeat_gap,repeat)==false)
		{
			DEBUG("GetGap failed\n");
			output("Error reading signal; please try again.");
			continue;
		}

		if(last_count==0)
		{
			for(i=0;i<3;i++) last_repeat[i]=repeat[i];
			last_count=count;
			last_gap=gap;
			last_repeat_gap=repeat_gap;
			output("Please wait a second and press it again.");
			continue;
		}

		match=true;
		/* match repeats */
		if(repeat[0]==0 && last_repeat[0]!=0) 
		{
			DEBUG("repeat[0] was zero but last_repeat[0] was %d\n",last_repeat[0]);
			match=false;
		}
		else if(last_repeat[0]==0 && repeat[0]!=0)
		{
			DEBUG("last_repeat[0] was zero but repeat[0] was %d\n",repeat[0]);
			match=false;
		}
		else {
			for(i=0;i<3;i++) 
				if(!expect(&remote,last_repeat[i],repeat[i])) 
				{
					DEBUG("repeat[%d]=%d doesn't match last_repeat[%d]=%d\n",
						i,repeat[i],i,last_repeat[i]);
					match=false;
				}
		}

		/* match counts */
		if(count!=last_count) 
		{
			DEBUG("Mismatched count: count=%d, last_count=%d\n",count,last_count);
			match=false;
		}

		/* match gaps */
		if(!expect(&remote,last_gap,gap))
		{
			DEBUG("gaps don't match: last_gap=%d, gap=%d\n",last_gap,gap);
			match=false;
		}

		/* match repeat gaps */
		if(!expect(&remote,last_repeat_gap,repeat_gap))
		{
			DEBUG("repeat gaps don't match: last_repeat_gap=%d, repeat_gap=%d\n",
				last_repeat_gap,repeat_gap);
			match=false;
		}


		if(!match)
		{
			for(i=0;i<3;i++) last_repeat[i]=repeat[i];
			last_count=count;
			last_gap=gap;
			last_repeat_gap=repeat_gap;
			fault++;
			if(fault>5)
			{
				MessageBox("Too many faults.  Possible reasons:\n"
					"1) This remote can't be automatically learned (sorry)\n"
					"2) The system is too slow or bogged down to accurately record\n"
					"      times (try closing all other programs)","Error");
				EndDialog2(IDCANCEL);
				DEBUG("LearnThread terminating\n");
				AfxEndThread(0);
				return;
			}
			DEBUG("Did not get consistent signal\n");
			output("Did not get a consistent signal; please try again.");
		}
	}

	/* Now, refine the information for gap and repeat */
	unsigned long avg_gap;
	unsigned long avg_repeat_gap;
	unsigned long avg_count;
	unsigned long avg_repeat[3];
	avg_count=count;
	avg_gap=(gap+last_gap)/2;
	avg_repeat_gap=(repeat_gap+last_repeat_gap)/2;
	for(i=0;i<3;i++) avg_repeat[i]=(repeat[i]+last_repeat[i])/2;
	int j=0;
	output("Baseline initialized.");
	while(j<10)
	{
		sprintf(s,"Please wait a second and press a button again (%d left)",10-j);
		output(s);
		if(GetGap(gap,count,repeat_gap,repeat)==false)
		{
			DEBUG("GetGap error\n");
			output("Error reading signal; please try again.");
			continue;
		}
		match=true;
		/* match repeats */
		if(repeat[0]==0 && avg_repeat[0]!=0) 
		{
			DEBUG("repeat[0] was zero but avg_repeat[0] was %d\n",avg_repeat[0]);
			match=false;
		}
		else if(avg_repeat[0]==0 && repeat[0]!=0)
		{
			DEBUG("avg_repeat[0] was zero but repeat[0] was %d\n",repeat[0]);
			match=false;
		}
		else if(avg_repeat[0]!=0) {
			for(i=0;i<3;i++) 
				if(!expect(&remote,avg_repeat[i],repeat[i])) 
				{
					DEBUG("repeat[%d]=%d doesn't match avg_repeat[%d]=%d\n",
						i,repeat[i],i,avg_repeat[i]);
					match=false;
				}
		}

		/* match counts */
		if(count!=avg_count) 
		{
			DEBUG("counts didn't match\n");
			match=false;
		}

		/* match gaps */
		if(!expect(&remote,avg_gap,gap))
		{
			DEBUG("gap was too far from old gap\n");
			match=false;
		}

		/* match repeat gaps */
		if(!expect(&remote,last_repeat_gap,repeat_gap))
		{
			DEBUG("repeat gaps was too far from old repeat gap\n");
			match=false;
		}


		if(!match)
		{
			fault++;
			if(fault>10)
			{
				MessageBox("Too many faults.  Possible reasons:\n"
					"1) This remote can't be automatically learned (sorry)\n"
					"2) The system is too slow or bogged down to accurately record\n"
					"      times (try closing all other programs)\n"
					"3) The detection got off to a bad start (try again)","Error");
				EndDialog2(IDCANCEL);
				DEBUG("LearnThread terminating\n");
				AfxEndThread(0);
				return;
			}
			output("Did not get a consistent signal.");
			continue;
		}
		else
		{
			avg_gap=((avg_gap*(j+2)) + gap)/(j+3);
			avg_repeat_gap=((avg_repeat_gap*(j+2)) + repeat_gap)/(j+3);
			for(i=0;i<3;i++) avg_repeat[i]=((avg_repeat[i]*(j+2)) + repeat[i])/(j+3);
			j++;
		}
	}

	/* Save it so far */
	code.length=avg_count;
	remote.gap=avg_gap;
	remote.repeat_gap=avg_repeat_gap;
	remote.prepeat=avg_repeat[0];
	remote.srepeat=avg_repeat[1];
	remote.ptrail=avg_repeat[2];

	fprint_comment(fout,&remote);
	fprint_remote_head(fout,&remote);
	fprint_remote_signal_head(fout,&remote);
}

bool Clearndlg::GetRawButton(unsigned long *signals, int &count, bool waitgap)
{
	count=0;
	unsigned long data;

	while(count<MAX_SIGNALS)
	{
		data=drv->readdata(waitgap?(30*1000*1000):(5*remote.gap),LearnThreadEvent);
		if(data==0) return false;

		if(waitgap)
		{
			if(!is_space(data) || data<remote.gap-remote.gap*remote.eps/100)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -