// RecorderTestDlg.cpp : implementation file // #include "stdafx.h" #include #include "RecorderTest.h" #include "RecorderTestDlg.h" #include "PlayWnd.h" #include "our_md5.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CRecorderTestDlg dialog CRecorderTestDlg::CRecorderTestDlg(CWnd* pParent /*=NULL*/) : CDialog(CRecorderTestDlg::IDD, pParent) { //{{AFX_DATA_INIT(CRecorderTestDlg) m_strIP = _T("192.168.13.4"); m_uPlayCh = 15; m_uPort = 2100; m_uPropCh = 0; m_uPropFileSize = 0; m_strPropList = _T(""); m_uPropNumList = 0; m_uPropPort = 0; m_uRecCh = 15; m_uSearchCh = 15; m_strRequest = _T(""); m_strResponse = _T(""); m_strSearchStart = _T(""); m_strSearchStop = _T(""); //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_uCmdSock = 0; m_uStreamSock = 0; m_hKillGetStream = NULL; m_hThreadGetStream = NULL; m_hThreadLocalPlaying = NULL; m_hKillLocalPlaying = NULL; m_uPlayingCh = 0; m_pPlayWnd = NULL; m_bPlaying = FALSE; m_bForceStop = FALSE; m_szLocalPath[0] = 0; ZeroMemory(m_fp, sizeof(m_fp)); } void CRecorderTestDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CRecorderTestDlg) DDX_Control(pDX, IDC_CHECK_LOCAL_PLAY, m_btnLocalPlay); DDX_Control(pDX, IDC_CHECK_PAUSE_PLAY, m_btnPause); DDX_Control(pDX, IDC_COMBO_PLAY_SPEED, m_cbPlaySpeed); DDX_Control(pDX, IDC_COMBO_PLAY_MODE, m_cbPlayMode); DDX_Control(pDX, IDC_COMBO_PLAY_DIRECTION, m_cbPlayDirection); DDX_Control(pDX, IDC_CHECK_START_RECORD, m_btnStartRecord); DDX_Control(pDX, IDC_CHECK_START_PLAY, m_btnStartPlay); DDX_Control(pDX, IDC_CHECK_CONNECT, m_btnConnect); DDX_Control(pDX, IDC_CHECK_MOUNT, m_btnMount); DDX_Control(pDX, IDC_BUTTON_NEXT_FRAME, m_btnNextFrame); DDX_Control(pDX, IDC_COMBO_SEARCH_DATA_TYPE, m_cbSearchDataType); DDX_Control(pDX, IDC_COMBO_PROP_RECYCLE, m_cbPropRecycle); DDX_Control(pDX, IDC_COMBO_PROP_ACTION, m_cbPropAction); DDX_Text(pDX, IDC_EDIT_IP, m_strIP); DDX_Text(pDX, IDC_EDIT_PLAY_CH, m_uPlayCh); DDX_Text(pDX, IDC_EDIT_PORT, m_uPort); DDX_Text(pDX, IDC_EDIT_PROP_CH, m_uPropCh); DDX_Text(pDX, IDC_EDIT_PROP_FILE_SIZE, m_uPropFileSize); DDX_Text(pDX, IDC_EDIT_PROP_LIST, m_strPropList); DDX_Text(pDX, IDC_EDIT_PROP_NUM, m_uPropNumList); DDX_Text(pDX, IDC_EDIT_PROP_PORT, m_uPropPort); DDX_Text(pDX, IDC_EDIT_REC_CH, m_uRecCh); DDX_Text(pDX, IDC_EDIT_SEARCH_CH, m_uSearchCh); DDX_Text(pDX, IDC_EDIT_REQUEST, m_strRequest); DDX_Text(pDX, IDC_EDIT_RESPONSE, m_strResponse); DDX_Text(pDX, IDC_EDIT_SEARCH_START, m_strSearchStart); DDX_Text(pDX, IDC_EDIT_SEARCH_STOP, m_strSearchStop); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CRecorderTestDlg, CDialog) //{{AFX_MSG_MAP(CRecorderTestDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON_SEARCH, OnButtonSearch) ON_BN_CLICKED(IDC_BUTTON_PROP_APPLY, OnButtonPropApply) ON_WM_DESTROY() ON_BN_CLICKED(IDC_CHECK_CONNECT, OnCheckConnect) ON_CBN_SELCHANGE(IDC_COMBO_PROP_ACTION, OnSelchangeComboPropAction) ON_BN_CLICKED(IDC_BUTTON_CLEAR, OnButtonClear) ON_BN_CLICKED(IDC_BUTTON_NEXT_FRAME, OnButtonNextFrame) ON_BN_CLICKED(IDC_CHECK_MOUNT, OnCheckMount) ON_BN_CLICKED(IDC_CHECK_START_RECORD, OnCheckStartRecord) ON_BN_CLICKED(IDC_CHECK_START_PLAY, OnCheckStartPlay) ON_BN_CLICKED(IDC_BUTTON_DELETE, OnButtonDelete) ON_BN_CLICKED(IDC_CHECK_PAUSE_PLAY, OnCheckPausePlay) ON_BN_CLICKED(IDC_BUTTON_BROWSE, OnButtonBrowse) ON_BN_CLICKED(IDC_CHECK_LOCAL_PLAY, OnCheckLocalPlay) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CRecorderTestDlg message handlers BOOL CRecorderTestDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here WSAStartup(MAKEWORD(2,2), &m_WsaData); m_cbPlayMode.AddString("Continuous"); m_cbPlayMode.AddString("Frame"); m_cbPlayMode.SetCurSel(0); m_cbPlayDirection.AddString("Forward"); m_cbPlayDirection.AddString("Backward"); m_cbPlayDirection.SetCurSel(0); m_cbPlaySpeed.AddString("0"); m_cbPlaySpeed.AddString("0.25"); m_cbPlaySpeed.AddString("0.5"); m_cbPlaySpeed.AddString("1"); m_cbPlaySpeed.AddString("2"); m_cbPlaySpeed.AddString("3"); m_cbPlaySpeed.SetCurSel(3); m_cbSearchDataType.AddString("Video"); //m_cbSearchDataType.AddString("Audio"); //m_cbSearchDataType.AddString("All"); m_cbSearchDataType.SetCurSel(0); m_cbPropRecycle.AddString("None"); m_cbPropRecycle.AddString("Rotate"); m_cbPropRecycle.SetCurSel(1); m_cbPropAction.AddString("Get"); m_cbPropAction.AddString("Set"); m_cbPropAction.SetCurSel(0); m_btnNextFrame.EnableWindow(FALSE); return TRUE; // return TRUE unless you set the focus to a control } void CRecorderTestDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CRecorderTestDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CRecorderTestDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CRecorderTestDlg::OnButtonSearch() { // TODO: Add your control notification handler code here UpdateData(TRUE); CString strDataType; switch(m_cbSearchDataType.GetCurSel()) { case 0: strDataType = "video"; break; case 1: strDataType = "audio"; break; case 2: strDataType = "video&data_type=audio"; break; } sprintf(m_szCmd, "action=set&cmd=search_data&data_type=%s&ch=%d&start_time=%s&stop_time=%s\r\n\r\n", strDataType, m_uSearchCh, m_strSearchStart, m_strSearchStop); SendCommand(); m_uPlayCh = m_uSearchCh; UpdateData(FALSE); } void CRecorderTestDlg::OnButtonPropApply() { // TODO: Add your control notification handler code here UpdateData(TRUE); CString strRecycle; char *pszToken; if (m_cbPropAction.GetCurSel() == 0) { sprintf(m_szCmd, "action=get&cmd=property&recycle&port&file_size&record_channel&num_of_list&search_list\r\n\r\n"); if (!SendCommand()) { return; } pszToken = strtok(m_szCmd, "&"); if (!pszToken) return; pszToken = strtok(NULL, "&"); if (!pszToken) return; pszToken = strtok(NULL, "&"); if (!pszToken) return; sscanf(pszToken, "%[a-zA-Z0-9_]=%[a-zA-Z0-9_]", m_szName, m_szValue); if (strcmp("none", m_szValue) == 0) { m_cbPropRecycle.SetCurSel(0); } else if (strcmp("rotate", m_szValue) == 0) { m_cbPropRecycle.SetCurSel(1); } pszToken = strtok(NULL, "&"); if (!pszToken) return; sscanf(pszToken, "%[a-zA-Z0-9_]=%[a-zA-Z0-9_]", m_szName, m_szValue); m_uPropPort = atoi(m_szValue); pszToken = strtok(NULL, "&"); if (!pszToken) return; sscanf(pszToken, "%[a-zA-Z0-9_]=%[a-zA-Z0-9_]", m_szName, m_szValue); m_uPropFileSize = atoi(m_szValue); pszToken = strtok(NULL, "&"); if (!pszToken) return; sscanf(pszToken, "%[a-zA-Z0-9_]=%[a-zA-Z0-9_]", m_szName, m_szValue); m_uPropCh = atoi(m_szValue); pszToken = strtok(NULL, "&"); if (!pszToken) return; sscanf(pszToken, "%[a-zA-Z0-9_]=%[a-zA-Z0-9_]", m_szName, m_szValue); m_uPropNumList = atoi(m_szValue); pszToken = strtok(NULL, "&"); if (!pszToken) return; sscanf(pszToken, "%[a-zA-Z0-9_]=%[a-zA-Z0-9_:-]", m_szName, m_szValue); m_strPropList = m_szValue; UpdateData(FALSE); char szList[1024]; strcpy(szList, pszToken); pszToken = strtok(szList, ":"); if (!pszToken) return; pszToken = strtok(NULL, ":"); if (!pszToken) return; sscanf(pszToken, "%[a-zA-Z0-9_]-%[a-zA-Z0-9_]", m_szName, m_szValue); m_strSearchStart = m_szName; m_strSearchStop = m_szValue; } else { strRecycle = m_cbPropRecycle.GetCurSel() == 0 ? "none" : "rotate"; sprintf(m_szCmd, "action=set&cmd=property&recycle=%s&port=%d&file_size=%d\r\n\r\n", strRecycle, m_uPropPort, m_uPropFileSize); SendCommand(); } UpdateData(FALSE); } void CRecorderTestDlg::OnDestroy() { CDialog::OnDestroy(); // TODO: Add your message handler code here StopGetStreamThread(TRUE); StopLocalPlayingThread(TRUE); if (m_uCmdSock) { closesocket(m_uCmdSock); } if (m_uStreamSock) { closesocket(m_uStreamSock); } if (m_pPlayWnd) { m_pPlayWnd->Release(); m_pPlayWnd->DestroyWindow(); delete m_pPlayWnd; m_pPlayWnd=NULL; } WSACleanup(); } void CRecorderTestDlg::OnCheckConnect() { // TODO: Add your control notification handler code here UpdateData(TRUE); if (m_btnConnect.GetCheck()) { m_uCmdSock = socket(AF_INET, SOCK_STREAM, 0); ZeroMemory(&m_CmdAddr, sizeof(m_CmdAddr)); m_CmdAddr.sin_family = AF_INET; m_CmdAddr.sin_addr.s_addr = inet_addr(m_strIP); m_CmdAddr.sin_port = htons(m_uPort); m_uStreamSock = socket(AF_INET, SOCK_STREAM, 0); ZeroMemory(&m_StreamAddr, sizeof(m_StreamAddr)); m_StreamAddr.sin_family = AF_INET; m_StreamAddr.sin_addr.s_addr = inet_addr(m_strIP); m_StreamAddr.sin_port = htons(m_uPort+1); if (connect(m_uCmdSock, (struct sockaddr*)&m_CmdAddr, sizeof(m_CmdAddr)) == SOCKET_ERROR) { MessageBox("Cannot connect to command port\n"); return; } if (connect(m_uStreamSock, (struct sockaddr*)&m_StreamAddr, sizeof(m_StreamAddr)) == SOCKET_ERROR) { MessageBox("Cannot connect to stream port\n"); return; } ZeroMemory(m_szCmd, sizeof(m_szCmd)); recv(m_uCmdSock, m_szCmd, sizeof(m_szCmd), 0); sscanf(m_szCmd, "%[a-zA-Z0-9_]=%[a-zA-Z0-9_]", m_szName, m_szValue); TRACE("%s=%s\n", m_szName, m_szValue); m_strResponse += m_szCmd; char szEncPass[32+1]; ZeroMemory(szEncPass, sizeof(szEncPass)); our_MD5Data((const UCHAR*)"pass", strlen("pass"), szEncPass); sprintf(m_szCmd, "action=set&cmd=login&id=root&pwd=%s\r\n\r\n", szEncPass); if (!SendCommand()) { return; } sprintf(m_szCmd, "%s=%s&id=root&pwd=%s\r\n\r\n", m_szName, m_szValue, szEncPass); //sprintf(m_szCmd, "%s=%s\r\n\r\n", m_szName, m_szValue); m_strRequest += m_szCmd; send(m_uStreamSock, m_szCmd, strlen(m_szCmd), 0); ZeroMemory(m_szCmd, sizeof(m_szCmd)); recv(m_uStreamSock, m_szCmd, sizeof(m_szCmd), 0); sscanf(m_szCmd, "%[a-zA-Z0-9_]=%[a-zA-Z0-9_]", m_szName, m_szValue); TRACE("%s=%s\n", m_szName, m_szValue); m_strResponse += m_szCmd; sprintf(m_szCmd, "action=get&cmd=mount&device&enable\r\n\r\n"); SendCommand(); if (strstr(m_szCmd, "enable=1")) { m_btnMount.SetCheck(1); m_btnMount.SetWindowText("Unmount"); } else if (strstr(m_szCmd, "enable=0")) { m_btnMount.SetCheck(0); m_btnMount.SetWindowText("Mount"); } sprintf(m_szCmd, "action=get&cmd=property&record_channel\r\n\r\n"); SendCommand(); char *pszStr = strstr(m_szCmd, "record_channel="); if (!pszStr) { return; } sscanf(pszStr, "%[a-zA-Z0-9_]=%[a-zA-Z0-9_]", m_szName, m_szValue); if (atoi(m_szValue) > 0) { m_btnStartRecord.SetCheck(1); m_btnStartRecord.SetWindowText("Stop"); } m_btnConnect.SetWindowText("Disconnect"); } else { if (m_btnStartPlay.GetCheck()) { m_btnStartPlay.SetCheck(0); OnCheckStartPlay(); } closesocket(m_uCmdSock); m_uCmdSock = 0; closesocket(m_uStreamSock); m_uStreamSock = 0; m_btnMount.SetCheck(0); m_btnMount.SetWindowText("Mount"); m_btnStartRecord.SetCheck(0); m_btnStartRecord.SetWindowText("Start"); m_btnConnect.SetWindowText("Connect"); } UpdateData(FALSE); } BOOL CRecorderTestDlg::SendCommand() { m_strRequest = m_szCmd + m_strRequest; send(m_uCmdSock, m_szCmd, strlen(m_szCmd), 0); ZeroMemory(m_szCmd, sizeof(m_szCmd)); recv(m_uCmdSock, m_szCmd, sizeof(m_szCmd), 0); m_strResponse = m_szCmd + m_strResponse; UpdateData(FALSE); if (strstr(m_szCmd, "failed")) { return FALSE; } return TRUE; } void CRecorderTestDlg::OnSelchangeComboPropAction() { // TODO: Add your control notification handler code here if (m_cbPropAction.GetCurSel() == 0) { CEdit *pEdit = (CEdit*)GetDlgItem(IDC_EDIT_PROP_CH); pEdit->EnableWindow(TRUE); pEdit = (CEdit*)GetDlgItem(IDC_EDIT_PROP_NUM); pEdit->EnableWindow(TRUE); pEdit = (CEdit*)GetDlgItem(IDC_EDIT_PROP_LIST); pEdit->EnableWindow(TRUE); } else { CEdit *pEdit = (CEdit*)GetDlgItem(IDC_EDIT_PROP_CH); pEdit->EnableWindow(FALSE); pEdit = (CEdit*)GetDlgItem(IDC_EDIT_PROP_NUM); pEdit->EnableWindow(FALSE); pEdit = (CEdit*)GetDlgItem(IDC_EDIT_PROP_LIST); pEdit->EnableWindow(FALSE); } } typedef unsigned (__stdcall *PTHREAD_START) (void *); #define chBEGINTHREADEX(psa, cbStack, pfnStartAddr, \ pvParam, fdwCreate, pdwThreadId) \ ((HANDLE)_beginthreadex( \ (void *) (psa), \ (unsigned) (cbStack), \ (PTHREAD_START) (pfnStartAddr), \ (void *) (pvParam), \ (unsigned) (fdwCreate), \ (unsigned *) (pdwThreadId))) BOOL CRecorderTestDlg::StartGetStreamThread() { ULONG uID; if (m_hKillGetStream || m_hThreadGetStream) { TRACE("Already run\n"); return FALSE; } m_hKillGetStream = CreateEvent(NULL, FALSE, FALSE, NULL); if (!m_hKillGetStream) { TRACE("Cannot create event\n"); return FALSE; } m_hThreadGetStream = chBEGINTHREADEX(NULL, 0, ThreadGetStreamStub, this, 0, &uID); if (!m_hThreadGetStream) { TRACE("Cannot create thread\n"); return FALSE; } return TRUE; } void CRecorderTestDlg::StopGetStreamThread(BOOL bKill) { if (m_hThreadGetStream && m_hKillGetStream) { if (bKill) { SetEvent(m_hKillGetStream); } WaitForSingleObject(m_hThreadGetStream, INFINITE); CloseHandle(m_hKillGetStream); m_hKillGetStream = NULL; CloseHandle(m_hThreadGetStream); m_hThreadGetStream = NULL; } } DWORD WINAPI CRecorderTestDlg::ThreadGetStreamStub(LPVOID lpParam) { return static_cast(lpParam)->ThreadGetStream(); } DWORD WINAPI CRecorderTestDlg::ThreadGetStream() { ULONG uTotal = 0; int iRead = 0; ULONG uPrev=0, uCur=0; ULONG uNumOfCh = MAX_CHANNEL; ULONG uPreTime=0, uCurTime=0; ULONG uStart=0, uStop=0; ULONG uExpected=0, uReal=0; ULONG uCount=0; BYTE pData[100*1024]; REC_DATA_HEADER Header; #if 0 FILE *fp[MAX_CHANNEL]; #endif fd_set rset; struct timeval tv; ULONG uPlayingCh = m_uPlayingCh; TRACE("Start thread\n"); memset(pData, 0, sizeof(pData)); #if 0 for (ULONG i=0; iChangeTime(TRUE); uStart = GetTickCount(); while (1) { ULONG uRs = WaitForSingleObject(m_hKillGetStream, 0); if (uRs == WAIT_OBJECT_0) { TRACE("Kill event detected\n"); break; } FD_ZERO(&rset); FD_SET(m_uStreamSock, &rset); tv.tv_sec = 1; tv.tv_usec = 0; int rs = select(m_uStreamSock+1, &rset, NULL, NULL, &tv); if (rs < 0) { break; } if (rs == 0) { continue; } uTotal = 0; iRead = 0; while (uTotal != sizeof(Header)) { iRead = recv(m_uStreamSock, ((char*)&Header)+uTotal, sizeof(Header)-uTotal, 0); if (iRead <= 0) { TRACE("Cannot receive data[%d]\n", WSAGetLastError()); break; } uTotal += iRead; } if (iRead <= 0) { break; } #if 0 if (uPreTime) { uCur = GetTickCount(); uCurTime = Header.TimeStamp.tv_sec*1000+Header.TimeStamp.tv_usec/1000; uExpected += (uCurTime-uPreTime); uReal += (uCur-uPrev); uCount++; uPrev = GetTickCount(); uPreTime = Header.TimeStamp.tv_sec*1000+Header.TimeStamp.tv_usec/1000; } else { uPrev = GetTickCount(); uPreTime = Header.TimeStamp.tv_sec*1000+Header.TimeStamp.tv_usec/1000; } uStop = GetTickCount(); if (uStop-uStart >= 1000) { TRACE("Expected[%d], Real[%d]\n", uExpected/uCount, uReal/uCount); uStart = GetTickCount(); uExpected = 0; uReal = 0; uCount = 0; } #endif #if 0 ShowHeaderInfo(&Header); #endif if (Header.uDataSize == 0) { uPlayingCh &= ~(1<DecodeVideo(&Header, pData)) { TRACE("Cannot decode video\n"); ShowHeaderInfo(&Header); //break; } } #if 0 for (i=0; iCreateEx(WS_EX_CLIENTEDGE, pszClassPlayWnd, _T("PlayWnd"), WS_POPUP | WS_CAPTION|WS_THICKFRAME|WS_THICKFRAME , 0, 0, 704, 480, NULL, NULL)) { return; } m_pPlayWnd->ShowWindow(TRUE); if (!m_pPlayWnd->Init()) { return; } strMode = m_cbPlayMode.GetCurSel() == 0 ? "continuous" : "frame"; strDirection = m_cbPlayDirection.GetCurSel() == 0 ? "forward" : "backward"; GetDlgItemText(IDC_COMBO_PLAY_SPEED, strSpeed); sprintf(m_szCmd, "action=set&cmd=start_playing&ch=%d&mode=%s&direction=%s&speed=%s\r\n\r\n", m_uPlayCh, strMode, strDirection, strSpeed); if (!SendCommand()) { return; } m_uPlayingCh |= m_uPlayCh; TRACE("Playing channel[%d]\n", m_uPlayingCh); if (m_cbPlayMode.GetCurSel() == 1) { m_btnNextFrame.EnableWindow(TRUE); } if (!StartGetStreamThread()) { return; } m_btnStartPlay.SetWindowText("Stop"); m_bForceStop = FALSE; } else { if (!m_bPlaying) { return; } m_bForceStop = TRUE; sprintf(m_szCmd, "action=set&cmd=stop_playing&ch=%d\r\n\r\n", m_uPlayingCh); SendCommand(); m_uPlayingCh &= ~(m_uPlayCh); TRACE("Playing channel[%d]\n", m_uPlayingCh); if (m_uPlayingCh == 0) { StopGetStreamThread(FALSE); } m_btnNextFrame.EnableWindow(FALSE); if (m_pPlayWnd) { m_pPlayWnd->Release(); m_pPlayWnd->DestroyWindow(); delete m_pPlayWnd; m_pPlayWnd=NULL; } m_bPlaying = FALSE; m_btnStartPlay.SetWindowText("Start"); if (m_btnPause.GetCheck()) { m_btnPause.SetCheck(0); OnCheckPausePlay(); } } UpdateData(FALSE); } void CRecorderTestDlg::ShowHeaderInfo(REC_DATA_HEADER *pHeader) { TRACE("###################################\n"); TRACE("Ver : %d\n", pHeader->uVer); TRACE("FrameType : %d\n", pHeader->uFrameType); TRACE("DataType : %d\n", pHeader->uDataType); TRACE("DataSize : %d\n", pHeader->uDataSize); TRACE("Channel : %d\n", pHeader->uChannelNum); TRACE("Width : %d\n", pHeader->MediaInfo.uWidth); TRACE("Height : %d\n", pHeader->MediaInfo.uHeight); struct tm *pGmt = gmtime(&pHeader->TimeStamp.tv_sec); TRACE("%04d%02d%02d%02d%02d%02d\n", pGmt->tm_year+1900, pGmt->tm_mon+1, pGmt->tm_mday, pGmt->tm_hour, pGmt->tm_min, pGmt->tm_sec); } void CRecorderTestDlg::OnButtonDelete() { // TODO: Add your control notification handler code here UpdateData(TRUE); sprintf(m_szCmd, "action=set&cmd=delete&file=all\r\n\r\n"); SendCommand(); UpdateData(FALSE); } void CRecorderTestDlg::OnCheckPausePlay() { // TODO: Add your control notification handler code here UpdateData(TRUE); if (m_uPlayingCh == 0) { return; } if (m_btnPause.GetCheck()) { sprintf(m_szCmd, "action=set&cmd=pause_playing&ch=%d\r\n\r\n", m_uPlayCh); SendCommand(); } else { CString strMode; if (m_cbPlayMode.GetCurSel() == 0) { strMode = "continuous"; m_btnNextFrame.EnableWindow(FALSE); } else { strMode = "frame"; m_btnNextFrame.EnableWindow(TRUE); } CString strDirection = m_cbPlayDirection.GetCurSel() == 0 ? "forward" : "backward"; CString strSpeed; GetDlgItemText(IDC_COMBO_PLAY_SPEED, strSpeed); sprintf(m_szCmd, "action=set&cmd=start_playing&ch=%d&mode=%s&direction=%s&speed=%s\r\n\r\n", m_uPlayCh, strMode, strDirection, strSpeed); SendCommand(); } } void CRecorderTestDlg::OnButtonBrowse() { // TODO: Add your control notification handler code here BROWSEINFO bi; ZeroMemory(&bi, sizeof(bi)); char szDisplayName[MAX_PATH]; szDisplayName[0] = '\0'; bi.hwndOwner = NULL; bi.pidlRoot = NULL; bi.pszDisplayName = szDisplayName; bi.lpszTitle = TEXT("Select the folder."); bi.ulFlags = BIF_VALIDATE ; bi.lParam = (LPARAM)(LPSTR)(LPCTSTR)m_szLocalPath; bi.iImage = 0; LPITEMIDLIST pidl = SHBrowseForFolder(&bi); if(NULL != pidl) { SHGetPathFromIDList(pidl, m_szLocalPath); } if(strlen(m_szLocalPath) < 1) { return; } SetDlgItemText(IDC_EDIT_LOCAL_PATH, m_szLocalPath); } void CRecorderTestDlg::OnCheckLocalPlay() { // TODO: Add your control notification handler code here if (m_btnLocalPlay.GetCheck()) { if (m_bPlaying) { return; } m_bPlaying = TRUE; if (!PasInit(m_szLocalPath)) { MessageBox("Cannot init parser library\n"); return; } m_pPlayWnd = new CPlayWnd(); LPCTSTR pszClassPlayWnd = AfxRegisterWndClass(CS_OWNDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, NULL, (HBRUSH)::GetStockObject(BLACK_BRUSH)); RECT rc; GetClientRect(&rc); if(!m_pPlayWnd->CreateEx(WS_EX_CLIENTEDGE, pszClassPlayWnd, _T("PlayWnd"), WS_POPUP | WS_CAPTION|WS_THICKFRAME|WS_THICKFRAME , 0, 0, 704, 480, NULL, NULL)) { return; } m_pPlayWnd->ShowWindow(TRUE); if (!m_pPlayWnd->Init()) { return; } if (!StartLocalPlayingThread()) { return; } m_bForceStop = FALSE; m_btnLocalPlay.SetWindowText("Stop"); } else { if (!m_bPlaying) { return; } m_bForceStop = TRUE; PasRelease(); StopLocalPlayingThread(TRUE); if (m_pPlayWnd) { m_pPlayWnd->Release(); m_pPlayWnd->DestroyWindow(); delete m_pPlayWnd; m_pPlayWnd=NULL; } m_bPlaying = FALSE; m_btnLocalPlay.SetWindowText("Play"); } } BOOL CRecorderTestDlg::StartLocalPlayingThread() { ULONG uID; if (m_hKillLocalPlaying || m_hThreadLocalPlaying) { TRACE("Already run\n"); return FALSE; } m_hKillLocalPlaying = CreateEvent(NULL, FALSE, FALSE, NULL); if (!m_hKillLocalPlaying) { TRACE("Cannot create event\n"); return FALSE; } m_hThreadLocalPlaying = chBEGINTHREADEX(NULL, 0, ThreadLocalPlayingStub, this, 0, &uID); if (!m_hThreadLocalPlaying) { TRACE("Cannot create thread\n"); return FALSE; } return TRUE; } void CRecorderTestDlg::StopLocalPlayingThread(BOOL bKill) { if (m_hThreadLocalPlaying && m_hKillLocalPlaying) { if (bKill) { SetEvent(m_hKillLocalPlaying); } WaitForSingleObject(m_hThreadLocalPlaying, INFINITE); CloseHandle(m_hKillLocalPlaying); m_hKillLocalPlaying = NULL; CloseHandle(m_hThreadLocalPlaying); m_hThreadLocalPlaying = NULL; } } DWORD WINAPI CRecorderTestDlg::ThreadLocalPlayingStub(LPVOID lpParam) { return static_cast(lpParam)->ThreadLocalPlaying(); } DWORD WINAPI CRecorderTestDlg::ThreadLocalPlaying() { PAS_DATA_INFO Info; m_pPlayWnd->ChangeTime(FALSE); while (1) { ULONG uRet = WaitForSingleObject(m_hKillLocalPlaying, 0); if (uRet == WAIT_OBJECT_0) { break; } if (!PasGetData(&Info)) { if (!m_bForceStop) { MessageBox("Got all data"); } break; } if (!m_pPlayWnd->DecodeVideo(&Info)) { TRACE("Cannot decode video\n"); } } CloseHandle(m_hKillLocalPlaying); m_hKillLocalPlaying = NULL; CloseHandle(m_hThreadLocalPlaying); m_hThreadLocalPlaying = NULL; return 0; }