using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Media;
using System.IO;
using NUUO_SDK;

namespace Tester_CSharp
{
    struct stSession
    {
        public IntPtr session;
        public Np_ID id;
        public int width;
        public int height;
    }

    struct ExportCbInfo
    {
        public Np_ID id;
        public Np_ExportError error; 
        public uint percent;
        public int iFormatChangedIndex;

        public ExportCbInfo(Np_ID _id, Np_ExportError _error, uint _percent, int _iFormatChangedIndex)
        {
            id = _id;
            error = _error;
            percent = _percent;
            iFormatChangedIndex = _iFormatChangedIndex;
        }
    }

    struct ExportProfileItem
    {
        public int format;
        public int profile;
        public string desc;

        public override string ToString()
        {
            return desc;
        }
    }

    public partial class Tester_CSharp : Form
    {
        private IntPtr m_handle = IntPtr.Zero;
        private IntPtr m_lvPlayer = IntPtr.Zero;
        private Dictionary<int, stSession> m_lvSessions = new Dictionary<int, stSession>();
        private IntPtr m_pbPlayer = IntPtr.Zero;
        private Dictionary<int, stSession> m_pbSessions = new Dictionary<int, stSession>();
        private Np_DeviceList_CS m_deviceList;
        private PlaySound m_soundPlayer = new PlaySound();
        private fnVideoHandle m_vcb = null;
        private fnAudioHandle m_acb = null;
        private fnErrorHandle m_ecb = null;
        private fnExportHandle m_exptcb = null;
        private fnOSDHandle m_osdcb = null;
        private Graphics m_gViewPort = null;
        private Bitmap m_currentFrame = null;
        private Object m_frameLock = new Object();
        private System.Timers.Timer m_timer;
        private bool m_bPBFileOpen = false;
        private bool m_bExporting = false;
        private int session_series_number = 0;
        private List<ExportCbInfo> m_exptcbinfos = new List<ExportCbInfo>();
        private System.Object m_exptcbmutex = new System.Object();
        private stSession m_exptctx;

        delegate string GetTextCallback(Control ctrl);
        delegate void SetTextCallback(Control ctrl, string text);
        delegate void SetEnabledCallback(Control ctrl, bool enabled);

        public Tester_CSharp()
        {
            InitializeComponent();
            m_vcb = new fnVideoHandle(VideoHandler);
            m_acb = new fnAudioHandle(AudioHandler);
            m_ecb = new fnErrorHandle(ErrorHandler);
            m_exptcb = new fnExportHandle(ExportHandler);
            m_osdcb = new fnOSDHandle(OSDHandler);
            FormClosing += new FormClosingEventHandler(FormClosingHandler);
            m_gViewPort = pbViewPort.CreateGraphics();
            m_timer = new System.Timers.Timer();
            m_timer.Interval = 10;
            m_timer.Elapsed += new System.Timers.ElapsedEventHandler(OnUpdateUI);
            m_timer.SynchronizingObject = this;
            m_timer.Start();
        }

        public void FormClosingHandler(object src, FormClosingEventArgs args)
        {
            m_timer.Stop();
            m_soundPlayer.Dispose();

            NpClient.Info_ReleaseDeviceList_CS(m_handle, ref m_deviceList);
 
            if (m_handle != IntPtr.Zero)
            {
                if (m_lvPlayer != IntPtr.Zero)
                {
                    int[] keys = new int[m_lvSessions.Count];
                    m_lvSessions.Keys.CopyTo(keys, 0);
                    for (int i = 0; i < m_lvSessions.Count; ++i)
                    {
                        NpClient.LiveView_DetachSession(m_lvPlayer, m_lvSessions[keys[i]].session);
                    }
                    NpClient.LiveView_DestroyPlayer(m_lvPlayer);
                }

                if (m_pbPlayer != IntPtr.Zero)
                {
                    if (m_bExporting)
                    {
                        NpClient.PlayBack_StopExport(m_pbPlayer);
                    }

                    int[] keys = new int[m_pbSessions.Count];
                    m_pbSessions.Keys.CopyTo(keys, 0);
                    for (int i = 0; i < m_pbSessions.Count; i++)
                    {
                        NpClient.PlayBack_DetachSession(m_pbPlayer, m_pbSessions[keys[i]].session);
                    }
                    NpClient.PlayBack_DestroyPlayer(m_pbPlayer);
                }
                NpClient.Destroy_Handle(m_handle);
            }
        }

        public void VideoHandler(   Np_DateTime time,
                                    IntPtr pBuffer,
                                    int len,
                                    int width,
                                    int height,
                                    IntPtr ctx)
        {
            Rectangle recViewPort = new Rectangle(0, 0, 640, 360);
            int ssn = ctx.ToInt32();
            stSession st = new stSession();
            st.width = width;
            st.height = height;
            if (m_lvSessions.ContainsKey(ssn))
            {
                st.id = m_lvSessions[ssn].id;
                st.session = m_lvSessions[ssn].session;
                m_lvSessions.Remove(ssn);
                m_lvSessions.Add(ssn, st);
            }
            else if (m_pbSessions.ContainsKey(ssn))
            {
                st.id = m_pbSessions[ssn].id;
                st.session = m_pbSessions[ssn].session;
                m_pbSessions.Remove(ssn);
                m_pbSessions.Add(ssn, st);
            }

            try
            {
                Rectangle recVideo = new Rectangle(0, 0, width, height);
                lock (m_frameLock)
                {
                    if (null == m_currentFrame || (m_currentFrame != null && (m_currentFrame.Width != width || m_currentFrame.Height != height)))
                    {
                        m_currentFrame = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                    }
                    System.Drawing.Imaging.BitmapData bmp_data = m_currentFrame.LockBits(recVideo,
                                                                                System.Drawing.Imaging.ImageLockMode.WriteOnly,
                                                                                System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                    byte[] buffer = new byte[len];
                    Marshal.Copy(pBuffer, buffer, 0, len);
                    Marshal.Copy(buffer, 0, bmp_data.Scan0, len);

                    m_currentFrame.UnlockBits(bmp_data);
                    m_gViewPort.DrawImage(m_currentFrame, recViewPort, recVideo, GraphicsUnit.Pixel);
                }
            }
            finally
            {
            }
        }

        public void AudioHandler(   Np_DateTime time,
                                    IntPtr pBuffer,
                                    int len,
                                    int bitsPerSample,
                                    int samplesPerSec,
                                    int channels,
                                    IntPtr ctx)
        {
            m_soundPlayer.WriteSoundData(pBuffer, len, channels, bitsPerSample, samplesPerSec);
        }

        public void ErrorHandler(Np_Error error, IntPtr ctx)
        {
            if (Np_Error.Np_ERROR_CONNECT_SUCCESS == error)
            {
                m_bPBFileOpen = true;
            }
        }

        public void ExportHandler(  Np_ID id, 
                                   Np_ExportError error, 
                                   uint percent,
                                   int iFormateChangedIndex,
                                   IntPtr ctx)
        {
            PutExportCbInfo(id, error, percent, iFormateChangedIndex);
        }

        public void OSDHandler( Np_ID id,
                               IntPtr buffer,
                               int width,
                               int height,
                               Np_DateTime time, 
                               IntPtr ctx)
        {
        }

        public string FormatExportFilePath(string basePath, int iFormatChangedIndex, string formatDesc)
        {
            string path = basePath;
            if (iFormatChangedIndex > 0)
            {
                path += string.Format("_%d", iFormatChangedIndex);
            }

            if (formatDesc.Contains("ASF"))
            {
                path += ".ASF";
            }
            if (formatDesc.Contains("AVI"))
            {
                path += ".AVI";
            }
            if (formatDesc.Contains("MOV"))
            {
                path += ".MOV";
            }

            return path;
        }

        public void OnUpdateUI(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (m_pbSessions.Count != 0)
            {
                Np_DateTime dateTime;
                NpClient.PlayBack_GetTime(m_pbPlayer, out dateTime);
                float fSpeed = 1.0f;
                NpClient.PlayBack_GetSpeed(m_pbPlayer, out fSpeed);

                Np_PlayerState pb_state = Np_PlayerState.kStateStopped;
                string StateStr = "";
                NpClient.PlayBack_GetPlayerState(m_pbPlayer, out pb_state);
                switch(pb_state)
                {
                    case Np_PlayerState.kStateStopped:
                    {
                        StateStr = "Stopped";
                        break;
                    }
                case Np_PlayerState.kStatePaused:
                    {
                        StateStr = "Paused";
                        break;
                    }
                case Np_PlayerState.kStateRunning:
                    {
                        StateStr = "Running";
                        break;
                    }
                    default:
                    {
                        StateStr = "";
                        break;
                    }
                }

                string strTime =    "Time : "+
                                    string.Format("{0:D4}", dateTime.year)+"\\"+
                                    string.Format("{0:D2}", dateTime.month)+"\\"+
                                    string.Format("{0:D2}", dateTime.day)+" "+
                                    string.Format("{0:D2}", dateTime.hour)+":"+
                                    string.Format("{0:D2}", dateTime.minute)+":"+
                                    string.Format("{0:D2}", dateTime.second)+"  "+
                                    "Speed : "+fSpeed+" "+
                                    "State : "+StateStr;
                SetText(lbPBTime, strTime);

                SetPlaybackButtonStatus(m_bPBFileOpen);
            }

            lock (m_exptcbmutex)
            {
                OnUpdateExportStatus();
            }
        }

        private void OnUpdateExportStatus()
        {
            if(m_exptcbinfos.Count > 0)
            {
                ExportCbInfo info = m_exptcbinfos[0];
                m_exptcbinfos.RemoveAt(0);
                if (info.error == Np_ExportError.kExportUpdateProgress)
                {
                    while (m_exptcbinfos.Count > 0)
                    {
                        ExportCbInfo next = m_exptcbinfos[0];
                        if (Np_ExportError.kExportUpdateProgress != next.error || info.percent != next.percent)
                        {
                            break;
                        }
                        m_exptcbinfos.RemoveAt(0);
                    }
                    pbExportProgress.Value = (int)info.percent;
                    lbExportPercent.Text = info.percent + "%";
                    return;
                }
                else if (info.error == Np_ExportError.kExportFormatChange)
                {
                    AddWaterMarkAfterExport(info.id, info.iFormatChangedIndex);
                    return;
                }

                switch(info.error)
                {
                    case Np_ExportError.kExportSuccess:
                    AddWaterMarkAfterExport(info.id, info.iFormatChangedIndex);
                    ShowText("Export Success");
                    break;
                case Np_ExportError.kExportCallbackError:
                    ShowText("Export Callback Error");
                    break;
                case Np_ExportError.kExportChannelEmpty:
                    ShowText("Export Channel Empty");
                    break;
                case Np_ExportError.kExportCueTimeError:
                    ShowText("Export CueTime Error");
                    break;
                case Np_ExportError.kExportDimesionError:
                    ShowText("Export Dimension Error");
                    break;
                case Np_ExportError.kExportNoData:
                    ShowText("No Data to Export");
                    break;
                case Np_ExportError.kExportFail:
                    ShowText("Export Fail");
                    if(cmbExportProfile.Items.Count > 0)
                    {
                        FileInfo fi = new FileInfo(tbExportPath.Text);
                        FileInfo fi2 = new FileInfo(FormatExportFilePath(fi.FullName.Substring(0, fi.FullName.Length - fi.Extension.Length), 
                                             info.iFormatChangedIndex, cmbExportProfile.Text));
                        if(fi2.Exists)
                        {
                            fi2.Delete();
                        }
                    }
                    break;
                case Np_ExportError.kExportMJpegMac:
                    ShowText("Export MJPEG to MOV format is not supported");
                    break;
                }
                m_bExporting = false;
                pbExportProgress.Value = 0;
                lbExportPercent.Text = "0%";
                m_exptcbinfos.Clear();
            }

            if((cmbExportProfile.Items.Count > 0) && m_bPBFileOpen)
            {
                btnExport.Enabled = !m_bExporting;
                btnStopExport.Enabled = m_bExporting;
            }
        }

        private string GetText(Control ctrl)
        {
            if (ctrl.InvokeRequired)
            {
                GetTextCallback cb = new GetTextCallback(GetText);
                return (string)(Invoke(cb, new object[] { ctrl }));
            }
            else
            {
                return ctrl.Text;
            }
        }

        private void SetText(Control ctrl, string text)
        {
            if (ctrl.InvokeRequired)
            {
                SetTextCallback cb = new SetTextCallback(SetText);
                Invoke(cb, new object[] { ctrl, text });
            }
            else
            {
                ctrl.Text = text;
            }
        }

        private void SetEnabled(Control ctrl, bool enabled)
        {
            if (ctrl.InvokeRequired)
            {
                SetEnabledCallback cb = new SetEnabledCallback(SetEnabled);
                Invoke(cb, new object[] { ctrl, enabled });
            }
            else
            {
                ctrl.Enabled = enabled;
            }
        }

        private void ConvertTime(DateTime src, out Np_DateTime dst)
        {
            dst.year = (ushort)src.Year;
            dst.month = (ushort)src.Month;
            dst.day = (ushort)src.Day;
            dst.hour = (ushort)src.Hour;
            dst.minute = (ushort)src.Minute;
            dst.second = (ushort)src.Second;
            dst.millisecond = (ushort)src.Millisecond;
        }

        private void ShowText(string str)
        {
            tbMessages.AppendText(str + "\r\n");
        }

        private void ShowText(string str, ref string toString)  //Pre-processing version, due to calling TextBox.AppendText too frequently will cause process busy updating and then hang
        {
            toString += str + "\r\n";
        }

        private void ShowResult(Np_Result ret)
        {
            switch (ret)
            {
                case Np_Result.Np_Result_OK:
                    ShowText("OK");
                    break;
                case Np_Result.Np_Result_CLI_FAULT:
                    ShowText("CLI_FAULT");
                    break;
                case Np_Result.Np_Result_SVR_FAULT:
                    ShowText("SVR_FAULT");
                    break;
                case Np_Result.Np_Result_USER_ERROR:
                    ShowText("USER_ERROR");
                    break;
                case Np_Result.Np_Result_FAILED:
                    ShowText("FAILED");
                    break;
                case Np_Result.Np_Result_NO_METHOD:
                    ShowText("NO_METHOD");
                    break;
                case Np_Result.Np_Result_NO_DATA:
                    ShowText("NO_DATA");
                    break;
                case Np_Result.Np_Result_SOCKET_ERROR:
                    ShowText("SOCKET_ERROR");
                    break;
                case Np_Result.Np_Result_INVALID_ARGUMENT:
                    ShowText("INVALID_ARGUMENT");
                    break;
                case Np_Result.Np_Result_FATAL_ERROR:
                    ShowText("FATAL_ERROR");
                    break;
                default:
                    ShowText("Np_Result is Unrecognizable !!!");
                    break;
            }
            ShowText("\r\n");
        }

        private void ShowTime(string title, Np_DateTime time)
        {
            ShowText(title);
            ShowText(
                "year = "+time.year+"\r\n"+
                "month = "+time.month+"\r\n"+
                "day = "+time.day+"\r\n"+
                "hour = "+time.hour+"\r\n"+
                "minute = "+time.minute+"\r\n"+
                "second = "+time.second+"\r\n"+
                "millisecond = "+time.millisecond);
            ShowText("\r\n");
        }

        private void ShowTime(string title, Np_DateTime time, ref string toString)
        {
            ShowText(title, ref toString);
            ShowText(
                "year = " + time.year + "\r\n" +
                "month = " + time.month + "\r\n" +
                "day = " + time.day + "\r\n" +
                "hour = " + time.hour + "\r\n" +
                "minute = " + time.minute + "\r\n" +
                "second = " + time.second + "\r\n" +
                "millisecond = " + time.millisecond, ref toString);
            ShowText("\r\n", ref toString);
        }

        private void ShowRecordDateList(Np_RecordDateList dateList)
        {
            if (0 == dateList.size)
            {
                ShowText("No Dates have Record Logs");
                return;
            }

            IntPtr cursor = dateList.dateList;
            for (int i=0; i < dateList.size; i++)
            {
                ShowTime("Record date", (Np_DateTime)(Marshal.PtrToStructure(cursor, typeof(Np_DateTime))));
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_DateTime)));
            }
        }

        public void ShowRecordLogItem(Np_RecordLogItem logItem, ref string toString)
        {
            ShowText("---Record Log---\n", ref toString);
            ShowID("Device ID", logItem.ID, ref toString);
            ShowTime("Reocord StartTime", logItem.startTime, ref toString);
            ShowTime("Reocord EndTime", logItem.endTime, ref toString);
        }

        public void ShowRecordLogs(Np_RecordLogList logList)
        {
            string finalLog = "";
            if (0 == logList.size)
            {
                ShowText("No Record Logs");
                return;
            }

            ShowText(logList.size + " Record Logs");
            IntPtr cursor = logList.logList;
            for (int i=0; i < logList.size; i++)
            {
                ShowRecordLogItem((Np_RecordLogItem)(Marshal.PtrToStructure(cursor, typeof(Np_RecordLogItem))), ref finalLog);
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_RecordLogItem)));
            }

            ShowText(finalLog);
        }

        public void ShowSchduleType(Np_ScheduleType schType)
        {
            ShowText("Schedule Type:");
            switch(schType)
            {
                case Np_ScheduleType.kScheduleNone:
                {
                    ShowText("kScheduleNone");
                    break;
                }
                case Np_ScheduleType.kScheduleRecordOnly:
                {
                    ShowText("kScheduleRecordOnly");
                    break;
                }
                case Np_ScheduleType.kScheduleMotionDetectOnly:
                {
                    ShowText("kScheduleMotionDetectOnly");
                    break;
                }
                case Np_ScheduleType.kScheduleRecordAndMotionDetect:
                {
                    ShowText("kScheduleRecordAndMotionDetect");
                    break;
                }
                case Np_ScheduleType.kScheduleRecordMovingOnly:
                {
                    ShowText("kScheduleRecordMovingOnly");
                    break;
                }
                case Np_ScheduleType.kScheduleRecordOnEvent:
                {
                    ShowText("kScheduleRecordOnEvent");
                    break;
                }
                case Np_ScheduleType.kScheduleUndefined:
                {
                    ShowText("kScheduleUndefined");
                    break;
                }
                case Np_ScheduleType.kScheduleRecordBoost:
                {
                    ShowText("kScheduleRecordBoost");
                    break;
                }
                default:
                {
                    ShowText("Schedule Type is Unrecognizable !!!");
                    break;
                }
            }
            ShowText("\r\n");
        }

        public void ShowScheduleLogItem(Np_ScheduleLogItem logItem)
        {
            ShowText("---Scheudle Log---\n");
            ShowID("Device ID", logItem.ID);
            ShowSchduleType(logItem.type);
            ShowTime("Scheudle StartTime", logItem.startTime);
            ShowTime("Scheudle EndTime", logItem.endTime);
        }

        public void ShowScheduleLogs(Np_ScheduleLogList logList)
        {
            if (0 == logList.size)
            {
                ShowText("No Schedule Logs");
                return;
            }

            IntPtr cursor = logList.logList;
            for (int i=0; i < logList.size; i++)
            {
                ShowScheduleLogItem((Np_ScheduleLogItem)(Marshal.PtrToStructure(cursor, typeof(Np_ScheduleLogItem))));
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_ScheduleLogItem)));
            }
        }
        
        public void ShowEvent(Np_Event _event)
        {
            string description = "Description: "+_event.description+"\r\n";
            string eventID = getEventIDText(_event.eventID);
            if (eventID.Length == 0)
            {
                return; //Ignore unrecognizable events
            }
            ShowID("Event Source ID", _event.sourceID);
            ShowTime("event occurTime", _event.occurTime);
            ShowText(eventID);
            ShowText("\r\n");
            ShowText(description);
        }

        public void ShowEventList(Np_EventList eventList)
        {
            if (0 == eventList.size)
            {
                ShowText("No Events");
                return;
            }

            IntPtr cursor = eventList.list;
            for (int i = 0; i < eventList.size; i++)
            {
                ShowEvent((Np_Event)(Marshal.PtrToStructure(cursor, typeof(Np_Event))));
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_Event)));
            }
        }

        private void ShowID(string str, Np_ID id)
        {
            ShowText(str);
            ShowText("centralID: " + id.centralID + "\r\nlocalID: " + id.localID + "\r\n");
        }

        private void ShowID(string str, Np_ID id, ref string toString)
        {
            ShowText(str, ref toString);
            ShowText("centralID: " + id.centralID + "\r\nlocalID: " + id.localID + "\r\n", ref toString);
        }

        private void ShowSubDevice(Np_SubDevice_CS sub_device)
        {
            ShowID("SubDeviceID", sub_device.ID);
            ShowText("Device Name:");
            ShowText(sub_device.name);
            ShowText("Device Description:");
            ShowText(sub_device.description);
        }

        private void ShowPTZCapability(Np_SubDevice_CS sub_device)
        {
            Np_Result ret = Np_Result.Np_Result_OK;
            long ptzCap = 0;
            ret = NpClient.Info_GetPTZCapability(m_handle, sub_device.ID, out ptzCap);
            if (ret == Np_Result.Np_Result_OK)
            {
                string szCapability = "PTZ capability supported:\r\n";
                if ((ptzCap & (long)Np_PTZCap.kPTZAreaZoom) != 0)
                    szCapability += "    Area Zoom\r\n";
                if ((ptzCap & (long)Np_PTZCap.kPTZAutoPan) != 0)
                    szCapability += "    Auto Pan\r\n";
                if ((ptzCap & (long)Np_PTZCap.kPTZFocus) != 0)
                    szCapability += "    Focus\r\n";
                if ((ptzCap & (long)Np_PTZCap.kPTZLilin) != 0)
                    szCapability += "    Lilin\r\n";
                if ((ptzCap & (long)Np_PTZCap.kPTZPane) != 0)
                    szCapability += "    Pane\r\n";
                if ((ptzCap & (long)Np_PTZCap.kPTZPreset) != 0)
                    szCapability += "    Preset\r\n";
                if ((ptzCap & (long)Np_PTZCap.kPTZSpeedDomeOSDMenu) != 0)
                    szCapability += "    Speed Dome OSD Menu\r\n";
                if ((ptzCap & (long)Np_PTZCap.kPTZTilt) != 0)
                    szCapability += "    Tilt\r\n";
                if ((ptzCap & (long)Np_PTZCap.kPTZZoom) != 0)
                    szCapability += "    Zoom\r\n";
                ShowText(szCapability);
            }
        }

        private void ShowPTZPreset(Np_PTZPreset_CS ptzPreset)
        {
            ShowText("=====PresetInfo\r\n");
            ShowText("PresetName: " + ptzPreset.presetName); 
            ShowText("PresetNo: " + ptzPreset.presetNo);
            ShowText("\r\n");
        }

        private void ShowPTZPresetList(Np_PTZPreset_CS_List ptzPresetList)
        {
            IntPtr cursor = ptzPresetList.items;
            for (int i = 0; i < ptzPresetList.size; ++i)
            {
                ShowPTZPreset((Np_PTZPreset_CS)Marshal.PtrToStructure(cursor, typeof(Np_PTZPreset_CS)));
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_PTZPreset_CS)));
            } 
        }

        private void ShowDevice(Np_Device_CS device)
        {
            ShowID("==========DeviceID", device.ID);
            ShowText("Device Name:");
            ShowText(device.name);
            ShowText("Device Description:");
            ShowText(device.description);

            ShowText("Sensor Device:\r\n");
            Np_SubDevice_CS_List list = device.SensorDevices;
            IntPtr cursor = list.items;
            for (int i = 0; i < list.size; ++i)
            {
                ShowSubDevice((Np_SubDevice_CS)Marshal.PtrToStructure(cursor, typeof(Np_SubDevice_CS)));
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_SubDevice_CS)));
            }
            ShowText("PTZ Device:\r\n");
            list = device.PTZDevices;
            cursor = list.items;
            for (int i = 0; i < list.size; ++i)
            {
                Np_SubDevice_CS sub_device = (Np_SubDevice_CS)Marshal.PtrToStructure(cursor, typeof(Np_SubDevice_CS));
                ShowSubDevice(sub_device);
                ShowPTZCapability(sub_device);
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_SubDevice_CS)));
            }
            ShowText("DI Device:\r\n");
            list = device.DIDevices;
            cursor = list.items;
            for (int i = 0; i < list.size; ++i)
            {
                ShowSubDevice((Np_SubDevice_CS)Marshal.PtrToStructure(cursor, typeof(Np_SubDevice_CS)));
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_SubDevice_CS)));
            }
            ShowText("DO Device:\r\n");
            list = device.DODevices;
            cursor = list.items;
            for (int i = 0; i < list.size; ++i)
            {
                ShowSubDevice((Np_SubDevice_CS)Marshal.PtrToStructure(cursor, typeof(Np_SubDevice_CS)));
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_SubDevice_CS)));
            }
            ShowText("Audio Device:\r\n");
            list = device.AudioDevices;
            cursor = list.items;
            for (int i = 0; i < list.size; ++i)
            {
                ShowSubDevice((Np_SubDevice_CS)Marshal.PtrToStructure(cursor, typeof(Np_SubDevice_CS)));
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_SubDevice_CS)));
            }
        }

        private void ShowDeviceGroup(Np_DeviceGroup_CS group)
        {
            ShowText("Group(Server) Name:");
            ShowText(group.name);
            ShowText("Group(Server) Description:");
            ShowText(group.description);
            ShowText("=====Cameras:\r\n");
            Np_Device_CS_List list = group.Camera;
            IntPtr cursor = list.items;
            for (int i = 0; i < list.size; ++i)
            {
                ShowDevice((Np_Device_CS)Marshal.PtrToStructure(cursor, typeof(Np_Device_CS)));
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_Device_CS)));
            }
            ShowText("=====IOBox:\r\n");
            list = group.IOBox;
            cursor = list.items;
            for (int i = 0; i < list.size; ++i)
            {
                ShowDevice((Np_Device_CS)Marshal.PtrToStructure(cursor, typeof(Np_Device_CS)));
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_Device_CS)));
            }
        }

        private void ShowDeviceList(Np_DeviceList_CS deviceList)
        {
            ShowText("Logical Group:\r\n");
            Np_DeviceGroup_CS_List list = deviceList.LogicalGroup;
            IntPtr cursor = list.items;
            for (int i = 0; i < list.size; ++i)
            {
                ShowDeviceGroup((Np_DeviceGroup_CS)Marshal.PtrToStructure(cursor, typeof(Np_DeviceGroup_CS)));
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_DeviceGroup_CS)));
            }

            ShowText("Physical Group:\r\n");
            list = deviceList.PhysicalGroup;
            cursor = list.items;
            for (int i = 0; i < list.size; ++i)
            {
                ShowDeviceGroup((Np_DeviceGroup_CS)Marshal.PtrToStructure(cursor, typeof(Np_DeviceGroup_CS)));
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_DeviceGroup_CS)));
            }
        }

        void ShowStreamProfile(Np_StreamProfile streamProfile)
        {
            switch(streamProfile)
            {
                case Np_StreamProfile.kProfileNormal:
                {
                    ShowText("kProfileNormal");
                    break;
                }
                case Np_StreamProfile.kProfileOriginal:
                {
                    ShowText("kProfileOriginal");
                    break;
                }
                case Np_StreamProfile.kProfileLow:
                {
                    ShowText("kProfileLow");
                    break;
                }
                case Np_StreamProfile.kProfileMinimum:
                {
                    ShowText("kProfileMinimum");
                    break;
                }
                default:
                {
                    ShowText("Stream Profile is Unrecognizable !!!");
                    break;
                }
            }
        }

        void ShowSensorProfile(Np_SensorProfile_CS sensorProfile)
        {
            ShowStreamProfile(sensorProfile.profile);
            ShowText("Bitrate: "+sensorProfile.bitrate);
            ShowText("Codec: "+sensorProfile.codec);
            ShowText("FrameRate: "+sensorProfile.frameRate);
            ShowText("Quality: "+sensorProfile.quality);
            ShowText("Resolution: "+sensorProfile.resolution);
            ShowText("----------\n");
        }

        void ShowSensorProfileList(Np_SensorProfile_CS_List sensorProfileList)
        {
            IntPtr cursor = sensorProfileList.items;
            for (int i = 0; i < sensorProfileList.size; ++i)
            {
                ShowSensorProfile((Np_SensorProfile_CS)Marshal.PtrToStructure(cursor, typeof(Np_SensorProfile_CS)));
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_SensorProfile_CS)));
            }
        }

        private static Np_ServerType checkServerType(string type)
        {
            if (type == "MainConsole_LiveView")
                return Np_ServerType.kMainConsoleLiveview;
            if (type == "MainConsole_Playback")
                return Np_ServerType.kMainConsolePlayback;
            if (type == "Corporate")
                return Np_ServerType.kCorporate;
            if (type == "Titan")
                return Np_ServerType.kTitan;
            return Np_ServerType.kCorporate;
        }

        private static Np_Event_Type checkEventID(string id)
        {
            if (id == "ALL")
            {
                return Np_Event_Type.Np_EVENT_CODE_BASE;
            }
            if (id == "Np_EVENT_MOTION_1")
            {
                return Np_Event_Type.Np_EVENT_GENERAL_MOTION_1;
            }
            if (id == "Np_EVENT_MOTION_2")
            {
                return Np_Event_Type.Np_EVENT_GENERAL_MOTION_2;
            }
            if (id == "Np_EVENT_MOTION_3")
            {
                return Np_Event_Type.Np_EVENT_GENERAL_MOTION_3;
            }
            if (id == "Np_EVENT_MOTION_4")
            {
                return Np_Event_Type.Np_EVENT_GENERAL_MOTION_4;
            }
            if (id == "Np_EVENT_MOTION_5")
            {
                return Np_Event_Type.Np_EVENT_GENERAL_MOTION_5;
            }
            if (id == "Np_EVENT_FOREIGN_OBJECT")
            {
                return Np_Event_Type.Np_EVENT_FOREIGN_OBJECT;
            }
            if (id == "Np_EVENT_MISSING_OBJECT")
            {
                return Np_Event_Type.Np_EVENT_MISSING_OBJECT;
            }
            if (id == "Np_EVENT_FOCUS_LOST")
            {
                return Np_Event_Type.Np_EVENT_FOCUS_LOST;
            }
            if (id == "Np_EVENT_CAMERA_OCCLUSION")
            {
                return Np_Event_Type.Np_EVENT_CAMERA_OCCLUSION;
            }
            if (id == "Np_EVENT_GENERAL_MOTION_DEVICE")
            {
                return Np_Event_Type.Np_EVENT_GENERAL_MOTION_DEVICE;
            }
            if (id == "Np_EVENT_SIGNAL_LOST")
            {
                return Np_Event_Type.Np_EVENT_SIGNAL_LOST;
            }
            if (id == "Np_EVENT_MOTION_START")
            {
                return Np_Event_Type.Np_EVENT_MOTION_START;
            }
            if (id == "Np_EVENT_MOTION_STOP")
            {
                return Np_Event_Type.Np_EVENT_MOTION_STOP;
            }
            if (id == "Np_EVENT_CONNECTION_LOST")
            {
                return Np_Event_Type.Np_EVENT_CONNECTION_LOST;
            }
            if (id == "Np_EVENT_MANUAL_RECORD_MODE_START")
            {
                return Np_Event_Type.Np_EVENT_MANUAL_RECORD_MODE_START;
            }
            if (id == "Np_EVENT_MANUAL_RECORD_MODE_STOP")
            {
                return Np_Event_Type.Np_EVENT_MANUAL_RECORD_MODE_STOP;
            }
            if (id == "Np_EVENT_INPUT_OPENED")
            {
                return Np_Event_Type.Np_EVENT_INPUT_OPENED;
            }
            if (id == "Np_EVENT_INPUT_CLOSED")
            {
                return Np_Event_Type.Np_EVENT_INPUT_CLOSED;
            }
            return Np_Event_Type.Np_EVENT_CODE_BASE;
        }

        public static string getEventIDText(Np_Event_Type ID)
        {
            switch (ID)
            {
                //------sensor
                case Np_Event_Type.Np_EVENT_GENERAL_MOTION_1:
                    return "Np_EVENT_MOTION_1";
                    break;
                case Np_Event_Type.Np_EVENT_GENERAL_MOTION_2:
                    return "Np_EVENT_MOTION_2";
                    break;
                case Np_Event_Type.Np_EVENT_GENERAL_MOTION_3:
                    return "Np_EVENT_MOTION_3";
                    break;
                case Np_Event_Type.Np_EVENT_GENERAL_MOTION_4:
                    return "Np_EVENT_MOTION_4";
                    break;
                case Np_Event_Type.Np_EVENT_GENERAL_MOTION_5:
                    return "Np_EVENT_MOTION_5";
                    break;
                case Np_Event_Type.Np_EVENT_FOREIGN_OBJECT:
                    return "Np_EVENT_FOREIGN_OBJECT";
                    break;
                case Np_Event_Type.Np_EVENT_MISSING_OBJECT:
                    return "Np_EVENT_MISSING_OBJECT";
                    break;
                case Np_Event_Type.Np_EVENT_FOCUS_LOST:
                    return "Np_EVENT_FOCUS_LOST";
                    break;
                case Np_Event_Type.Np_EVENT_CAMERA_OCCLUSION:
                    return "Np_EVENT_CAMERA_OCCLUSION";
                    break;
                case Np_Event_Type.Np_EVENT_GENERAL_MOTION_DEVICE:
                    return "Np_EVENT_GENERAL_MOTION_DEVICE";
                    break;
                case Np_Event_Type.Np_EVENT_SIGNAL_LOST:
                    return "Np_EVENT_SIGNAL_LOST";
                    break;
                case Np_Event_Type.Np_EVENT_MOTION_START:
                    return "Np_EVENT_MOTION_START";
                    break;
                case Np_Event_Type.Np_EVENT_MOTION_STOP:
                    return "Np_EVENT_MOTION_STOP";
                    break;
                case Np_Event_Type.Np_EVENT_CONNECTION_LOST:
                    return "Np_EVENT_CONNECTION_LOST";
                    break;
                case Np_Event_Type.Np_EVENT_MANUAL_RECORD_MODE_START:
                    return "Np_EVENT_MANUAL_RECORD_MODE_START";
                    break;
                case Np_Event_Type.Np_EVENT_MANUAL_RECORD_MODE_STOP:
                    return "Np_EVENT_MANUAL_RECORD_MODE_STOP";
                    break;
                case Np_Event_Type.Np_EVENT_INPUT_OPENED:
                    return "Np_EVENT_INPUT_OPENED";
                    break;
                case Np_Event_Type.Np_EVENT_INPUT_CLOSED:
                    return "Np_EVENT_INPUT_CLOSED";
                    break;
                default:
                    return "";
                    break;
            }
        }

        static Np_StreamProfile checkStreamProfile(string profile)
        {
            if (profile == "Normal")
            {
                return Np_StreamProfile.kProfileNormal;
            }
            if (profile == "Original")
            {
                return Np_StreamProfile.kProfileOriginal;
            }
            if (profile == "Low")
            {
                return Np_StreamProfile.kProfileLow;
            }
            if (profile == "Minimum")
            {
                return Np_StreamProfile.kProfileMinimum;
            }

            return Np_StreamProfile.kProfileNormal;
        }

        private void SetLiveviewPTZUIStatus(Np_ID camID, bool disableAll)
        {
            long ptzCap = 0;
            if (!disableAll)
            {
                Np_DeviceGroup_CS_List list = m_deviceList.PhysicalGroup;
                IntPtr cursor = list.items;
                for (int i = 0; i < list.size; ++i)
                {
                    Np_DeviceGroup_CS group = ((Np_DeviceGroup_CS)Marshal.PtrToStructure(cursor, typeof(Np_DeviceGroup_CS)));

                    Np_Device_CS_List device_list = group.Camera;
                    IntPtr cursor2 = device_list.items;
                    for (int j = 0; j < device_list.size; ++j)
                    {
                        Np_Device_CS device = ((Np_Device_CS)Marshal.PtrToStructure(cursor2, typeof(Np_Device_CS)));
                        if (device.ID.centralID == camID.centralID &&
                            device.ID.localID == camID.localID)
                        {
                            if (device.PTZDevices.size > 0)
                            {
                                Np_SubDevice_CS sub_device = ((Np_SubDevice_CS)Marshal.PtrToStructure(device.PTZDevices.items, typeof(Np_SubDevice_CS)));
                                NpClient.Info_GetPTZCapability(m_handle, sub_device.ID, out ptzCap);
                            }
                        }
                        cursor2 = (IntPtr)(cursor2.ToInt32() + Marshal.SizeOf(typeof(Np_Device_CS)));
                    }
                    cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_DeviceGroup_CS)));
                }
            }

            btnZoomIn.Enabled = (ptzCap & (long)Np_PTZCap.kPTZZoom) != 0;
            btnZoomOut.Enabled = (ptzCap & (long)Np_PTZCap.kPTZZoom) != 0;

            btnFocusNear.Enabled = (ptzCap & (long)Np_PTZCap.kPTZFocus) != 0;
            btnFocusFar.Enabled = (ptzCap & (long)Np_PTZCap.kPTZFocus) != 0;

            btnUp.Enabled = (ptzCap & (long)Np_PTZCap.kPTZTilt) != 0;
            btnDown.Enabled = (ptzCap & (long)Np_PTZCap.kPTZTilt) != 0;

            btnLeft.Enabled = (ptzCap & (long)Np_PTZCap.kPTZPane) != 0;
            btnRight.Enabled = (ptzCap & (long)Np_PTZCap.kPTZPane) != 0;

            btnHome.Enabled = (ptzCap != 0);

            btnGetPTZPreset.Enabled = (ptzCap != 0);
            btnPresetGo.Enabled = (ptzCap != 0);
            btnPresetClear.Enabled = (ptzCap != 0);
            btnPresetSet.Enabled = (ptzCap != 0);
            lbPresetNumber.Enabled = (ptzCap != 0);
            tbPresetNumber.Enabled = (ptzCap != 0);
            lbPresetSetName.Enabled = (ptzCap != 0);
            tbPresetSetName.Enabled = (ptzCap != 0);
        }

        private void SetPlaybackButtonStatus(bool bFileOpen)
        {
            SetEnabled(btnPlay, bFileOpen);
            SetEnabled(btnPause, bFileOpen);
            SetEnabled(btnPrevious, bFileOpen);
            SetEnabled(btnNext, bFileOpen);
            SetEnabled(btnSeek, bFileOpen);
            SetEnabled(btnForward, bFileOpen);
            SetEnabled(btnBackward, bFileOpen);
        }

        private void PutExportCbInfo(Np_ID id, Np_ExportError error, uint percent, int iFormateChangedIndex)
        {
            lock (m_exptcbmutex)
            {
                m_exptcbinfos.Add(new ExportCbInfo(id, error, percent, iFormateChangedIndex));
            }
        }

        private void SetExportProfileList()
        {
            Np_ExportFormatList fmtlist = new Np_ExportFormatList();
            Np_Result ret = NpClient.PlayBack_GetExportFormatList(m_pbPlayer, ref fmtlist);
            if(Np_Result.Np_Result_OK == ret)
            {
                cmbExportProfile.Items.Clear();
                IntPtr cursor = fmtlist.items;
                for(int i = 0; i < fmtlist.size; ++i)
                {
                    Np_ExportFormat fmt = (Np_ExportFormat)Marshal.PtrToStructure(cursor, typeof(Np_ExportFormat));
                    cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_ExportFormat)));
                    ExportProfileItem epi = new ExportProfileItem();
                    string desc_base = fmt.description;
                    epi.desc = desc_base;
                    epi.format = fmt.format;
                    epi.profile = 0;
                    if(0 == fmt.supportedProfile.size)
                    {
                        cmbExportProfile.Items.Add(epi);
                        continue;
                    }

                    IntPtr cursor2 = fmt.supportedProfile.items;
                    for(int j = 0; j < fmt.supportedProfile.size; ++j)
                    {
                        Np_ExportProfile profile = (Np_ExportProfile)Marshal.PtrToStructure(cursor2, typeof(Np_ExportProfile));
                        cursor2 = (IntPtr)(cursor2.ToInt32() + Marshal.SizeOf(typeof(Np_ExportProfile)));
                        epi.desc = desc_base + " - " + profile.description;
                        epi.profile = profile.profile;
                        cmbExportProfile.Items.Add(epi);
                    }
                }
                ret = NpClient.PlayBack_ReleaseExportFormatList(m_pbPlayer, ref fmtlist);
                cmbExportProfile.SelectedIndex = 0;
            }
        }

        private void AddWaterMarkAfterExport(Np_ID id, int iFormatChangedIndex)
        {
            FileInfo fi = new FileInfo(tbExportPath.Text);
            string filpath = FormatExportFilePath(fi.FullName.Substring(0, fi.FullName.Length - fi.Extension.Length), 
                                                    iFormatChangedIndex, cmbExportProfile.Text);
            Np_DateTime startTime, endTime;
            ConvertTime(dtspFrom.Value, out startTime);
            ConvertTime(dtspTo.Value, out endTime);

            string camera_name = GetCameraName(id);

            NpClient.Utility_AddVideoWaterMark(filpath, ref startTime, ref endTime, camera_name);
        }

        private string GetCameraName(Np_ID id)
        {
            Np_DeviceGroup_CS_List list = m_deviceList.PhysicalGroup;
            IntPtr cursor = list.items;
            for (int i = 0; i < list.size; ++i)
            {
                Np_DeviceGroup_CS group = ((Np_DeviceGroup_CS)Marshal.PtrToStructure(cursor, typeof(Np_DeviceGroup_CS)));

                Np_Device_CS_List device_list = group.Camera;
                IntPtr cursor2 = device_list.items;
                for (int j = 0; j < device_list.size; ++j)
                {
                    Np_Device_CS device = ((Np_Device_CS)Marshal.PtrToStructure(cursor2, typeof(Np_Device_CS)));
                    if (device.ID.centralID == id.centralID &&
                        device.ID.localID == id.localID)
                    {
                        return device.name;
                    }

                    Np_SubDevice_CS_List sensor_list = device.SensorDevices;
                    IntPtr cursor3 = sensor_list.items;
                    for (int k = 0; k < sensor_list.size; ++k)
                    {
                        Np_SubDevice_CS sensor = ((Np_SubDevice_CS)Marshal.PtrToStructure(cursor3, typeof(Np_SubDevice_CS)));
                        if (sensor.ID.centralID == id.centralID &&
                            sensor.ID.localID == id.localID)
                        {
                            return device.name;
                        }
                        cursor3 = (IntPtr)(cursor3.ToInt32() + Marshal.SizeOf(typeof(Np_SubDevice_CS)));
                    }
                    cursor2 = (IntPtr)(cursor2.ToInt32() + Marshal.SizeOf(typeof(Np_Device_CS)));
                }
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_DeviceGroup_CS)));
            }

            return "";
        }

        //-----------------------------------------                       ----------------------------------------------------//
        //-----------------------------------------        General        ----------------------------------------------------//
        //-----------------------------------------                       ----------------------------------------------------//
        private void btnCreateHandle_Click(object sender, EventArgs e)
        {
            ShowText("*** Create_HandleWChar ***\r\n");
            Np_ServerType type = checkServerType((string)(cmbServerType.SelectedItem));
            Np_Result ret = NpClient.Create_HandleWChar(ref m_handle, 
                                                        type, 
                                                        tbUsername.Text, 
                                                        tbPassword.Text, 
                                                        tbIP.Text, 
                                                        Int32.Parse(tbPort.Text));

            ShowResult(ret);

            if (Np_Result.Np_Result_OK == ret)
            {
                NpClient.Info_GetDeviceList_CS(m_handle, ref m_deviceList);

                cmbEventID.Items.Clear();
                if(Np_ServerType.kMainConsolePlayback == type)
                {
                    cmbEventID.Items.Add("ALL");
                    cmbEventID.Items.Add("Np_EVENT_MOTION_1");
                    cmbEventID.Items.Add("Np_EVENT_MOTION_2");
                    cmbEventID.Items.Add("Np_EVENT_MOTION_3");
                    cmbEventID.Items.Add("Np_EVENT_MOTION_4");
                    cmbEventID.Items.Add("Np_EVENT_MOTION_5");
                    cmbEventID.Items.Add("Np_EVENT_FOREIGN_OBJECT");
                    cmbEventID.Items.Add("Np_EVENT_MISSING_OBJECT");
                    cmbEventID.Items.Add("Np_EVENT_FOCUS_LOST");
                    cmbEventID.Items.Add("Np_EVENT_CAMERA_OCCLUSION");
                    cmbEventID.Items.Add("Np_EVENT_GENERAL_MOTION_DEVICE");
                    cmbEventID.Items.Add("Np_EVENT_SIGNAL_LOST");
                    cmbEventID.Enabled = true;
                }
                else if(Np_ServerType.kCorporate == type)
                {
                    cmbEventID.Items.Add("ALL");
                    cmbEventID.Items.Add("Np_EVENT_MOTION_START");
                    cmbEventID.Items.Add("Np_EVENT_MOTION_STOP");
                    cmbEventID.Items.Add("Np_EVENT_CONNECTION_LOST");
                    cmbEventID.Items.Add("Np_EVENT_MANUAL_RECORD_MODE_START");
                    cmbEventID.Items.Add("Np_EVENT_MANUAL_RECORD_MODE_STOP");
                    cmbEventID.Items.Add("Np_EVENT_INPUT_OPENED");
                    cmbEventID.Items.Add("Np_EVENT_INPUT_CLOSED");
                    cmbEventID.Enabled = true;

                    btnGetScheduleLogs.Enabled = false;
                }
            }
        }

        private void btnGetDeviceList_Click(object sender, EventArgs e)
        {
            Np_Result ret = NpClient.Info_ReleaseDeviceList_CS(m_handle, ref m_deviceList);
            ret = NpClient.Info_GetDeviceList_CS(m_handle, ref m_deviceList);
            ShowText("*** GetDeviceList_CS ***\r\n");
            ShowResult(ret);
            ShowDeviceList(m_deviceList);
        }

        private void btnSubscribeEvent_Click(object sender, EventArgs e)
        {
        }

        private void btnUnsubscribeEvent_Click(object sender, EventArgs e)
        {

        }

        private void btnDestroyHandle_Click(object sender, EventArgs e)
        {
            ShowText("*** Destroy_Handle ***\r\n");
            Np_Result ret = Np_Result.Np_Result_OK;
            if (IntPtr.Zero == m_handle)
                ShowText("handle is null...");

            cmbEventID.Enabled = true;

            NpClient.Info_ReleaseDeviceList_CS(m_handle, ref m_deviceList);

            ret = NpClient.Destroy_Handle(m_handle);
            ShowResult(ret);
            m_handle = IntPtr.Zero;
            m_lvSessions.Clear();
            m_pbSessions.Clear();
            m_lvPlayer = IntPtr.Zero;
            m_pbPlayer = IntPtr.Zero;
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            tbMessages.Clear();
        }

        //-----------------------------------------                       ----------------------------------------------------//
        //-----------------------------------------        LiveView       ----------------------------------------------------//
        //-----------------------------------------                       ----------------------------------------------------//

        private void btnCreatePlayer_LV_Click(object sender, EventArgs e)
        {
            Np_Result ret = NpClient.LiveView_CreatePlayer(m_handle, ref m_lvPlayer);
            ShowText("*** LiveView_CreatePlayer ***\r\n");
            ShowResult(ret);
        }

        private void btnGetSensorProfile_Click(object sender, EventArgs e)
        {
            Np_ID id;
            Np_Result ret = Np_Result.Np_Result_OK;    
            id.centralID = Int32.Parse(tbCentralID.Text);
            id.localID = Int32.Parse(tbLocalID.Text);

            Np_DeviceGroup_CS_List list = m_deviceList.PhysicalGroup;
            IntPtr cursor = list.items;
            for (int i = 0; i < list.size; ++i)
            {
                Np_DeviceGroup_CS group = ((Np_DeviceGroup_CS)Marshal.PtrToStructure(cursor, typeof(Np_DeviceGroup_CS)));

                Np_Device_CS_List device_list = group.Camera;
                IntPtr cursor2 = device_list.items;
                for (int j = 0; j < device_list.size; ++j)
                {
                    Np_Device_CS device = ((Np_Device_CS)Marshal.PtrToStructure(cursor2, typeof(Np_Device_CS)));

                    Np_SubDevice_CS_List sub_device_list = device.SensorDevices;
                    IntPtr cursor3 = sub_device_list.items;
                    for (int k = 0; k < sub_device_list.size; ++k)
                    {
                        Np_SubDevice_CS sub_device = ((Np_SubDevice_CS)Marshal.PtrToStructure(cursor3, typeof(Np_SubDevice_CS)));
                        if(sub_device.ID.centralID == id.centralID &&
                            sub_device.ID.localID == id.localID)
                        {
                            Np_SensorProfile_CS_List profileList = new Np_SensorProfile_CS_List();
                            ShowText("***...Get Sensor Profile List...***"); 
                            ret = NpClient.Info_GetSensorProfileList_CS(
                                m_handle, 
                                id, 
                                ref profileList
                                );
                            ShowSensorProfileList(profileList);
                            ShowResult(ret);
                            NpClient.Info_ReleaseSensorProfileList_CS(m_handle, ref profileList);
                            return;
                        }
                        cursor3 = (IntPtr)(cursor3.ToInt32() + Marshal.SizeOf(typeof(Np_SubDevice_CS)));
                    }
                    cursor2 = (IntPtr)(cursor2.ToInt32() + Marshal.SizeOf(typeof(Np_Device_CS)));
                }
                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_DeviceGroup_CS)));
            }
            ShowText("***...No this Sensor device...***\n"); 
        }

        private void btnAttachSession_LV_Click(object sender, EventArgs e)
        {
            ShowText("***...AttachSession...***");    
            Np_Result ret = Np_Result.Np_Result_OK;    
            stSession st = new stSession();
            st.id.centralID = Int32.Parse(tbCentralID.Text);
            st.id.localID = Int32.Parse(tbLocalID.Text);
            IntPtr ctx = new IntPtr(session_series_number);

            for (int i = 0; i < m_lvSessions.Count; ++i)
            {
                int[] keys = new int[m_lvSessions.Count];
                m_lvSessions.Keys.CopyTo(keys, 0);
                if (m_lvSessions[keys[i]].id.centralID == st.id.centralID &&
                    m_lvSessions[keys[i]].id.localID == st.id.localID)
                {
                    ShowText("***...Already attach this session...***");
                    return;
                }
            }

            Np_StreamProfile profileID = checkStreamProfile(cmbProfileSelect.Text);
           
            ShowID("Attach ID:", st.id);
            ret = NpClient.LiveView_AttachSessionExt(   m_lvPlayer, ref st.session, st.id,
                                                        profileID,
                                                                Np_PixelFormat.kPixelFormatRGB24,
                                                                m_vcb, ctx,
                                                                m_acb, ctx, 
                                                                m_ecb, ctx);

            if (Np_Result.Np_Result_OK == ret)
            {
                m_lvSessions.Add(session_series_number, st);
                ++session_series_number;
                m_soundPlayer.StartPlay();
                SetLiveviewPTZUIStatus(st.id, false);
            }

            ShowResult(ret);
        }

        private void btnDetachSession_LV_Click(object sender, EventArgs e)
        {
            m_soundPlayer.StopPlay();

            ShowText("***...DetachSession...***");
            Np_Result ret = Np_Result.Np_Result_OK; 

            Np_ID id;
            id.centralID = Int32.Parse(tbCentralID.Text);
            id.localID = Int32.Parse(tbLocalID.Text);
            for(int i = 0; i < m_lvSessions.Count; ++i)
            {
                int[] keys = new int[m_lvSessions.Count];
                m_lvSessions.Keys.CopyTo(keys, 0);
                if (m_lvSessions[keys[i]].id.centralID == id.centralID &&
                    m_lvSessions[keys[i]].id.localID == id.localID)
                {
                    ret = NpClient.LiveView_DetachSession(
                        m_lvPlayer,
                        m_lvSessions[keys[i]].session       
                        );
                    ShowResult(ret);
                    m_lvSessions.Remove(keys[i]);
                    if (m_lvSessions.Count > 0)
                    {
                        keys = new int[m_lvSessions.Count];
                        m_lvSessions.Keys.CopyTo(keys, 0);
                        SetLiveviewPTZUIStatus(m_lvSessions[keys[m_lvSessions.Count - 1]].id, false);
                    }
                    else
                    {
                        SetLiveviewPTZUIStatus(id, true);
                    }
                    return;
                }
            }
            ShowText("***...No Such session...***"); 
        }

        private void btnSetAudioOn_Click(object sender, EventArgs e)
        {
            ShowText("*** LiveView_SetAudioOn ***\r\n");
            Np_Result ret = Np_Result.Np_Result_INVALID_ARGUMENT;
            Np_ID id;
            id.centralID = Int32.Parse(tbCentralID.Text);
            id.localID = Int32.Parse(tbLocalID.Text);
            for (int i = 0; i < m_lvSessions.Count; ++i)
            {
                int[] keys = new int[m_lvSessions.Count];
                m_lvSessions.Keys.CopyTo(keys, 0);
                if (m_lvSessions[keys[i]].id.centralID == id.centralID &&
                    m_lvSessions[keys[i]].id.localID == id.localID)
                {
                    ret = NpClient.LiveView_SetAudioOn(m_lvPlayer, m_lvSessions[keys[i]].session);
                    ShowResult(ret);
                    return;
                }
            }
            
            ShowResult(ret);
        }

        private void btnSetAudioOff_Click(object sender, EventArgs e)
        {
            ShowText("*** LiveView_SetAudioOff ***\r\n");
            Np_Result ret = NpClient.LiveView_SetAudioOff(m_lvPlayer);
            ShowResult(ret);
        }

        private void btnDestroyPlayer_Click(object sender, EventArgs e)
        {
            ShowText("*** LiveView_DestroyPlayer ***\r\n");
            Np_Result ret = NpClient.LiveView_DestroyPlayer(m_lvPlayer);
            m_lvPlayer = IntPtr.Zero;
            m_lvSessions.Clear();
            ShowResult(ret);
        }

        private void btnGetDIStatus_Click(object sender, EventArgs e)
        {
            Np_ID id;
            Np_DIOStatus status = Np_DIOStatus.kDIO_OFF;
            Np_Result ret = Np_Result.Np_Result_OK;
            id.centralID = Int32.Parse(tbCentralID.Text);
            id.localID = Int32.Parse(tbLocalID.Text);

            Np_DeviceGroup_CS_List list = m_deviceList.PhysicalGroup;
            IntPtr cursor = list.items;
            for (int i = 0; i < list.size; ++i)
            {
                Np_DeviceGroup_CS group = ((Np_DeviceGroup_CS)Marshal.PtrToStructure(cursor, typeof(Np_DeviceGroup_CS)));

                Np_Device_CS_List device_list = group.Camera;
                IntPtr cursor2 = device_list.items;
                for (int j = 0; j < device_list.size; ++j)
                {
                    Np_Device_CS device = ((Np_Device_CS)Marshal.PtrToStructure(cursor2, typeof(Np_Device_CS)));

                    Np_SubDevice_CS_List sub_device_list = device.DIDevices;
                    IntPtr cursor3 = sub_device_list.items;
                    for (int k = 0; k < sub_device_list.size; ++k)
                    {
                        Np_SubDevice_CS sub_device = ((Np_SubDevice_CS)Marshal.PtrToStructure(cursor3, typeof(Np_SubDevice_CS)));
                        if(sub_device.ID.centralID == id.centralID &&
                            sub_device.ID.localID == id.localID)
                        {
                            ShowText("***...Show DI Status...***"); 

                            ret = NpClient.Info_GetDIOStatus(m_handle, id, out status);

                            ShowResult(ret);
                            ShowText("DI Status = " + (int)status + "\r\n");
                            ShowText("==========\r\n"); 
                            return;
                        }
                        cursor3 = (IntPtr)(cursor3.ToInt32() + Marshal.SizeOf(typeof(Np_SubDevice_CS)));
                    }

                    cursor2 = (IntPtr)(cursor2.ToInt32() + Marshal.SizeOf(typeof(Np_Device_CS)));
                }

                device_list = group.IOBox;
                cursor2 = device_list.items;
                for (int j = 0; j < device_list.size; ++j)
                {
                    Np_Device_CS device = ((Np_Device_CS)Marshal.PtrToStructure(cursor2, typeof(Np_Device_CS)));

                    Np_SubDevice_CS_List sub_device_list = device.DIDevices;
                    IntPtr cursor3 = sub_device_list.items;
                    for (int k = 0; k < sub_device_list.size; ++k)
                    {
                        Np_SubDevice_CS sub_device = ((Np_SubDevice_CS)Marshal.PtrToStructure(cursor3, typeof(Np_SubDevice_CS)));
                        if (sub_device.ID.centralID == id.centralID &&
                            sub_device.ID.localID == id.localID)
                        {
                            ShowText("***...Show DI Status...***");

                            ret = NpClient.Info_GetDIOStatus(m_handle, id, out status);

                            ShowResult(ret);
                            ShowText("DI Status = " + (int)status + "\r\n");
                            ShowText("==========\r\n");
                            return;
                        }
                        cursor3 = (IntPtr)(cursor3.ToInt32() + Marshal.SizeOf(typeof(Np_SubDevice_CS)));
                    }

                    cursor2 = (IntPtr)(cursor2.ToInt32() + Marshal.SizeOf(typeof(Np_Device_CS)));
                }

                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_DeviceGroup_CS)));
            }
           
            ShowText("***...No this DI device...***\n");
        }

        private void btnGetDOStatus_Click(object sender, EventArgs e)
        {
            Np_ID id;
            Np_DIOStatus status = Np_DIOStatus.kDIO_OFF;
            Np_Result ret = Np_Result.Np_Result_OK;
            id.centralID = Int32.Parse(tbCentralID.Text);
            id.localID = Int32.Parse(tbLocalID.Text);

            Np_DeviceGroup_CS_List list = m_deviceList.PhysicalGroup;
            IntPtr cursor = list.items;
            for (int i = 0; i < list.size; ++i)
            {
                Np_DeviceGroup_CS group = ((Np_DeviceGroup_CS)Marshal.PtrToStructure(cursor, typeof(Np_DeviceGroup_CS)));

                Np_Device_CS_List device_list = group.Camera;
                IntPtr cursor2 = device_list.items;
                for (int j = 0; j < device_list.size; ++j)
                {
                    Np_Device_CS device = ((Np_Device_CS)Marshal.PtrToStructure(cursor2, typeof(Np_Device_CS)));

                    Np_SubDevice_CS_List sub_device_list = device.DODevices;
                    IntPtr cursor3 = sub_device_list.items;
                    for (int k = 0; k < sub_device_list.size; ++k)
                    {
                        Np_SubDevice_CS sub_device = ((Np_SubDevice_CS)Marshal.PtrToStructure(cursor3, typeof(Np_SubDevice_CS)));
                        if (sub_device.ID.centralID == id.centralID &&
                            sub_device.ID.localID == id.localID)
                        {
                            ShowText("***...Show DO Status...***");

                            ret = NpClient.Info_GetDIOStatus(m_handle, id, out status);

                            ShowResult(ret);
                            ShowText("DO Status = " + (int)status + "\r\n");
                            ShowText("==========\r\n");
                            return;
                        }
                        cursor3 = (IntPtr)(cursor3.ToInt32() + Marshal.SizeOf(typeof(Np_SubDevice_CS)));
                    }

                    cursor2 = (IntPtr)(cursor2.ToInt32() + Marshal.SizeOf(typeof(Np_Device_CS)));
                }

                device_list = group.IOBox;
                cursor2 = device_list.items;
                for (int j = 0; j < device_list.size; ++j)
                {
                    Np_Device_CS device = ((Np_Device_CS)Marshal.PtrToStructure(cursor2, typeof(Np_Device_CS)));

                    Np_SubDevice_CS_List sub_device_list = device.DODevices;
                    IntPtr cursor3 = sub_device_list.items;
                    for (int k = 0; k < sub_device_list.size; ++k)
                    {
                        Np_SubDevice_CS sub_device = ((Np_SubDevice_CS)Marshal.PtrToStructure(cursor3, typeof(Np_SubDevice_CS)));
                        if (sub_device.ID.centralID == id.centralID &&
                            sub_device.ID.localID == id.localID)
                        {
                            ShowText("***...Show DO Status...***");

                            ret = NpClient.Info_GetDIOStatus(m_handle, id, out status);

                            ShowResult(ret);
                            ShowText("DO Status = " + (int)status + "\r\n");
                            ShowText("==========\r\n");
                            return;
                        }
                        cursor3 = (IntPtr)(cursor3.ToInt32() + Marshal.SizeOf(typeof(Np_SubDevice_CS)));
                    }

                    cursor2 = (IntPtr)(cursor2.ToInt32() + Marshal.SizeOf(typeof(Np_Device_CS)));
                }

                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_DeviceGroup_CS)));
            }

            ShowText("***...No this DO device...***\n");
        }

        private void btnControlDO_Click(object sender, EventArgs e)
        {
            Np_ID id;
            Np_Result ret = Np_Result.Np_Result_OK;
            id.centralID = Int32.Parse(tbCentralID.Text);
            id.localID = Int32.Parse(tbLocalID.Text);

            Np_DeviceGroup_CS_List list = m_deviceList.PhysicalGroup;
            IntPtr cursor = list.items;
            for (int i = 0; i < list.size; ++i)
            {
                Np_DeviceGroup_CS group = ((Np_DeviceGroup_CS)Marshal.PtrToStructure(cursor, typeof(Np_DeviceGroup_CS)));

                Np_Device_CS_List device_list = group.Camera;
                IntPtr cursor2 = device_list.items;
                for (int j = 0; j < device_list.size; ++j)
                {
                    Np_Device_CS device = ((Np_Device_CS)Marshal.PtrToStructure(cursor2, typeof(Np_Device_CS)));

                    Np_SubDevice_CS_List sub_device_list = device.DODevices;
                    IntPtr cursor3 = sub_device_list.items;
                    for (int k = 0; k < sub_device_list.size; ++k)
                    {
                        Np_SubDevice_CS sub_device = ((Np_SubDevice_CS)Marshal.PtrToStructure(cursor3, typeof(Np_SubDevice_CS)));
                        if (sub_device.ID.centralID == id.centralID &&
                            sub_device.ID.localID == id.localID)
                        {
                            ShowText("***...Control Digital Output...***");
                            ret = NpClient.Control_DigitalOutput(
                                m_handle,
                                id,
                                (cmbControlDO.Text == "TurnOn")
                                );

                            ShowText(cmbControlDO.Text + " DO\r\n");
                            ShowResult(ret);
                            return;
                        }
                        cursor3 = (IntPtr)(cursor3.ToInt32() + Marshal.SizeOf(typeof(Np_SubDevice_CS)));
                    }

                    cursor2 = (IntPtr)(cursor2.ToInt32() + Marshal.SizeOf(typeof(Np_Device_CS)));
                }

                device_list = group.IOBox;
                cursor2 = device_list.items;
                for (int j = 0; j < device_list.size; ++j)
                {
                    Np_Device_CS device = ((Np_Device_CS)Marshal.PtrToStructure(cursor2, typeof(Np_Device_CS)));

                    Np_SubDevice_CS_List sub_device_list = device.DODevices;
                    IntPtr cursor3 = sub_device_list.items;
                    for (int k = 0; k < sub_device_list.size; ++k)
                    {
                        Np_SubDevice_CS sub_device = ((Np_SubDevice_CS)Marshal.PtrToStructure(cursor3, typeof(Np_SubDevice_CS)));
                        if (sub_device.ID.centralID == id.centralID &&
                            sub_device.ID.localID == id.localID)
                        {
                            ShowText("***...Control Digital Output...***");
                            ret = NpClient.Control_DigitalOutput(
                                m_handle,
                                id,
                                (cmbControlDO.Text == "TurnOn")
                                );

                            ShowText(cmbControlDO.Text + " DO\r\n");
                            ShowResult(ret);
                            return;
                        }
                        cursor3 = (IntPtr)(cursor3.ToInt32() + Marshal.SizeOf(typeof(Np_SubDevice_CS)));
                    }

                    cursor2 = (IntPtr)(cursor2.ToInt32() + Marshal.SizeOf(typeof(Np_Device_CS)));
                }

                cursor = (IntPtr)(cursor.ToInt32() + Marshal.SizeOf(typeof(Np_DeviceGroup_CS)));
            }

            ShowText("***...No this DO device...***\n");
        }

        private void PTZPan(Np_PanDirection direction)
        {
            Np_PTZContinuousMove ptzMoveDirection = new Np_PTZContinuousMove();
            ptzMoveDirection.pan = direction;
            PTZMove(ref ptzMoveDirection);
        }

        private void PTZTilt(Np_TiltDirection direction)
        {
            Np_PTZContinuousMove ptzMoveDirection = new Np_PTZContinuousMove();
            ptzMoveDirection.tilt = direction;
            PTZMove(ref ptzMoveDirection);
        }

        private void PTZZoom(Np_ZoomDirection direction)
        {
            Np_PTZContinuousMove ptzMoveDirection = new Np_PTZContinuousMove();
            ptzMoveDirection.zoom = direction;
            PTZMove(ref ptzMoveDirection);
        }

        private void PTZFocus(Np_FocusDirection direction)
        {
            Np_PTZContinuousMove ptzMoveDirection = new Np_PTZContinuousMove();
            ptzMoveDirection.focus = direction;
            PTZMove(ref ptzMoveDirection);
        }

        private void PTZMove(ref Np_PTZContinuousMove ptzMoveDirection)
        {
            Np_PTZControlParam_CS ptzParam = new Np_PTZControlParam_CS();

            ptzParam.command = Np_PTZCommand.kPTZContinuousMove;
            ptzParam.param.move = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Np_PTZContinuousMove)));
            Marshal.StructureToPtr(ptzMoveDirection, ptzParam.param.move, false);

            Np_ID id;
            id.centralID = Int32.Parse(tbCentralID.Text);
            id.localID = Int32.Parse(tbLocalID.Text);

            NpClient.Control_PTZ_PTZDeviceID_CS(m_handle, id, ref ptzParam);
            System.Threading.Thread.Sleep(300);
            PTZStop(ptzParam, ref ptzMoveDirection);
            Marshal.FreeHGlobal(ptzParam.param.move);
        }

        private void PTZStop(Np_PTZControlParam_CS ptzControlParam, ref Np_PTZContinuousMove ptzMoveCommand)
        {
            ptzControlParam.command = Np_PTZCommand.kPTZStop;
            //Stop previous PTZ command
            Np_ID id;
            id.centralID = Int32.Parse(tbCentralID.Text);
            id.localID = Int32.Parse(tbLocalID.Text);
            NpClient.Control_PTZ_PTZDeviceID_CS(m_handle, id, ref ptzControlParam);
        }

        private void btnZoomIn_Click(object sender, EventArgs e)
        {
            PTZZoom(Np_ZoomDirection.kZoomIn);
        }

        private void btnZoomOut_Click(object sender, EventArgs e)
        {
            PTZZoom(Np_ZoomDirection.kZoomOut);
        }

        private void btnFocusNear_Click(object sender, EventArgs e)
        {
            PTZFocus(Np_FocusDirection.kFocusNear);
        }

        private void btnFocusFar_Click(object sender, EventArgs e)
        {
            PTZFocus(Np_FocusDirection.kFocusFar);
        }

        private void btnUp_Click(object sender, EventArgs e)
        {
            PTZTilt(Np_TiltDirection.kTiltUp);
        }

        private void btnDown_Click(object sender, EventArgs e)
        {
            PTZTilt(Np_TiltDirection.kTiltDown);
        }

        private void btnLeft_Click(object sender, EventArgs e)
        {
            PTZPan(Np_PanDirection.kPanLeft);
        }

        private void btnRight_Click(object sender, EventArgs e)
        {
            PTZPan(Np_PanDirection.kPanRight);
        }

        private void btnHome_Click(object sender, EventArgs e)
        {
            Np_PTZControlParam_CS ptzParam = new Np_PTZControlParam_CS();
            Np_PTZContinuousMove ptzMoveDirection = new Np_PTZContinuousMove();

            ptzParam.command = Np_PTZCommand.kPTZHome;
            ptzParam.param.move = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Np_PTZContinuousMove)));
            Marshal.StructureToPtr(ptzMoveDirection, ptzParam.param.move, false);

            Np_ID id;
            id.centralID = Int32.Parse(tbCentralID.Text);
            id.localID = Int32.Parse(tbLocalID.Text);

            NpClient.Control_PTZ_PTZDeviceID_CS(m_handle, id, ref ptzParam);
            System.Threading.Thread.Sleep(300);
            PTZStop(ptzParam, ref ptzMoveDirection);
            Marshal.FreeHGlobal(ptzParam.param.move);
        }

        private void btnGetPTZPreset_Click(object sender, EventArgs e)
        {
            ShowText("***...GetPTZPreset...***");

            Np_ID id;
            id.centralID = Int32.Parse(tbCentralID.Text);
            id.localID = Int32.Parse(tbLocalID.Text);

            Np_Result ret = Np_Result.Np_Result_OK;
            Np_PTZPreset_CS_List ptzPresetList = new Np_PTZPreset_CS_List();
            ret = NpClient.Info_GetPTZPreset_CS(
                    m_handle,
                    id,
                    ref ptzPresetList
                    );
            ShowPTZPresetList(ptzPresetList);
            ShowResult(ret);
            NpClient.Info_ReleasePTZPreset_CS(m_handle, ref ptzPresetList);
        }

        private void btnPresetGo_Click(object sender, EventArgs e)
        {
            ShowText("***...PresetGo...***");

            Np_PTZControlParam_CS ptzParam = new Np_PTZControlParam_CS();
            Np_PTZPreset_CS ptzPreset = new Np_PTZPreset_CS();

            ptzPreset.presetName = "";
            ptzPreset.presetNo = Int32.Parse(tbPresetNumber.Text);

            ptzParam.command = Np_PTZCommand.kPTZPresetGo;
            ptzParam.param.preset = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Np_PTZPreset_CS)));
            Marshal.StructureToPtr(ptzPreset, ptzParam.param.preset, false);

            Np_ID id;
            id.centralID = Int32.Parse(tbCentralID.Text);
            id.localID = Int32.Parse(tbLocalID.Text);

            Np_Result ret = Np_Result.Np_Result_OK;
            ret = NpClient.Control_PTZ_PTZDeviceID_CS(m_handle, id, ref ptzParam);
            ShowResult(ret);
            Marshal.FreeHGlobal(ptzParam.param.preset);
        }

        private void btnPresetClear_Click(object sender, EventArgs e)
        {
            Np_PTZControlParam_CS ptzParam = new Np_PTZControlParam_CS();
            Np_PTZPreset_CS ptzPreset = new Np_PTZPreset_CS();

            ptzPreset.presetName = "";
            ptzPreset.presetNo = Int32.Parse(tbPresetNumber.Text);

            ptzParam.command = Np_PTZCommand.kPTZPresetClear;
            ptzParam.param.preset = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Np_PTZPreset_CS)));
            Marshal.StructureToPtr(ptzPreset, ptzParam.param.preset, false);

            Np_ID id;
            id.centralID = Int32.Parse(tbCentralID.Text);
            id.localID = Int32.Parse(tbLocalID.Text);

            Np_Result ret = Np_Result.Np_Result_OK;
            ret = NpClient.Control_PTZ_PTZDeviceID_CS(m_handle, id, ref ptzParam);
            ShowResult(ret);
            Marshal.FreeHGlobal(ptzParam.param.preset);
        }

        private void btnPresetSet_Click(object sender, EventArgs e)
        {
            Np_PTZControlParam_CS ptzParam = new Np_PTZControlParam_CS();
            Np_PTZPreset_CS ptzPreset = new Np_PTZPreset_CS();

            ptzPreset.presetName = tbPresetSetName.Text;

            ptzParam.command = Np_PTZCommand.kPTZPresetSet;
            ptzParam.param.preset = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Np_PTZPreset_CS)));
            Marshal.StructureToPtr(ptzPreset, ptzParam.param.preset, false);

            Np_ID id;
            id.centralID = Int32.Parse(tbCentralID.Text);
            id.localID = Int32.Parse(tbLocalID.Text);

            Np_Result ret = Np_Result.Np_Result_OK;
            ret = NpClient.Control_PTZ_PTZDeviceID_CS(m_handle, id, ref ptzParam);
            ShowResult(ret);
            Marshal.FreeHGlobal(ptzParam.param.preset);
        }

        //-----------------------------------------                       ----------------------------------------------------//
        //-----------------------------------------        Playback       ----------------------------------------------------//
        //-----------------------------------------                       ----------------------------------------------------//

        private void btnCreatePlayer_PB_Click(object sender, EventArgs e)
        {
            ShowText("***...CreatePBPlayer...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            ret = NpClient.PlayBack_CreatePlayer(
                m_handle,
                ref m_pbPlayer
                );

            if (Np_Result.Np_Result_OK == ret)
            {
                SetExportProfileList();
            }

            ShowResult(ret);
        }

        private void btnAttachSession_PB_Click(object sender, EventArgs e)
        {
            ShowText("***...AttachSession...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            stSession st = new stSession();
            st.id.centralID = Int32.Parse(tbCentralID_PB.Text);
            st.id.localID = Int32.Parse(tbLocalID_PB.Text);
            ShowID("Attach ID:", st.id);
            IntPtr ctx = new IntPtr(session_series_number);

            ret = NpClient.PlayBack_AttachSessionExt(
                m_pbPlayer,
                ref st.session,
                st.id,
                Np_PixelFormat.kPixelFormatRGB24,
                m_vcb, ctx,
                m_acb, ctx,
                m_ecb, ctx
                );

            if (Np_Result.Np_Result_OK == ret)
            {
                m_pbSessions.Add(session_series_number, st);
                ++session_series_number;
                m_soundPlayer.StartPlay();
            }
            ShowResult(ret);  
        }

        private void btnDetachSession_PB_Click(object sender, EventArgs e)
        {
            m_soundPlayer.StopPlay();

            ShowText("***...DetachSession...***");    
            Np_Result ret = Np_Result.Np_Result_INVALID_ARGUMENT;

            Np_ID id;
            id.centralID = Int32.Parse(tbCentralID_PB.Text);
            id.localID = Int32.Parse(tbLocalID_PB.Text);
            for(int i = 0; i < m_pbSessions.Count; ++i)
            {
                int[] keys = new int[m_pbSessions.Count];
                m_pbSessions.Keys.CopyTo(keys, 0);
                if (m_pbSessions[keys[i]].id.centralID == id.centralID && 
                    m_pbSessions[keys[i]].id.localID == id.localID)
                {
                    ret = NpClient.PlayBack_DetachSession(
                        m_pbPlayer,
                        m_pbSessions[keys[i]].session        
                        );
                    ShowResult(ret);
                    m_pbSessions.Remove(keys[i]);
                    return;
                }
            }

            ShowResult(ret);
        }

        private void btnDestroyPlayer_PB_Click(object sender, EventArgs e)
        {
            ShowText("***...DestroyPlayer...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            ret = NpClient.PlayBack_DestroyPlayer(
                m_pbPlayer
                );
            m_pbPlayer = IntPtr.Zero;
            m_pbSessions.Clear();
            ShowResult(ret); 
        }

        int getMonthDays(int year, int month)
        {
            int[] month_days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

            if(2 == month && 0 == year % 4)
            {
                return 29;
            }

            return month_days[month - 1];
        }

        private void btnGetRecordDateList_Click(object sender, EventArgs e)
        {
            ShowText("***...GetRecordDateList...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            Np_RecordDateList dateList = new Np_RecordDateList();
            if (Np_ServerType.kCorporate == checkServerType(cmbServerType.Text))
            {
                ShowText("Range applied : ");
                Np_DateTime start, end;
                DateTime dt = dtspQueryDate.Value;
                DateTime dtStart = new DateTime(dt.Year, dt.Month, 1, 0, 0, 0);
                ConvertTime(dtStart, out start);
                ShowTime("Start date", start);
                DateTime dtEnd = new DateTime(dt.Year, dt.Month, getMonthDays(dt.Year, dt.Month), 0, 0, 0);
                ConvertTime(dtEnd, out end);
                ShowTime("End date", end);
                IntPtr ptrStart = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Np_DateTime)));
                Marshal.StructureToPtr(start, ptrStart, false);
                IntPtr ptrEnd = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Np_DateTime)));
                Marshal.StructureToPtr(end, ptrEnd, false);
                ret = NpClient.Info_GetRangedRecordDateList(
                    m_handle,
                    ptrStart,
                    ptrEnd,
                    ref dateList
                    );
                ShowText("==========\n");
                Marshal.FreeHGlobal(ptrStart);
                Marshal.FreeHGlobal(ptrEnd);
            }
            else
            {
                ret = NpClient.Info_GetRangedRecordDateList(
                    m_handle,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    ref dateList
                    );
            }
            if (Np_Result.Np_Result_OK == ret)
            {
                ShowRecordDateList(dateList);
                NpClient.Info_ReleaseRecordDateList(m_handle, ref dateList);
            }
            ShowResult(ret);
        }

        private void btnGetRecordLogs_Click(object sender, EventArgs e)
        {
            ShowText("***...GetRecordLogs...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            Np_RecordLogList logList = new Np_RecordLogList();
            Np_DateTime queryTime;
            ConvertTime(dtspQueryDate.Value, out queryTime);
            ret = NpClient.Info_GetRecordLogs(
                m_handle,
                queryTime,
                ref logList
                );
            if (Np_Result.Np_Result_OK == ret)
            {
                ShowRecordLogs(logList);
                NpClient.Info_ReleaseRecordLogs(m_handle, ref logList);
            }
            ShowResult(ret);
        }

        private void btnGetScheduleLogs_Click(object sender, EventArgs e)
        {
            ShowText("***...GetScheduleLogs...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            Np_ScheduleLogList logList = new Np_ScheduleLogList();
            Np_DateTime queryTime;
            ConvertTime(dtspQueryDate.Value, out queryTime);
            ret = NpClient.Info_GetScheduleLogs(
                m_handle,
                queryTime,
                ref logList
                );
            if (Np_Result.Np_Result_OK == ret)
            {
                ShowScheduleLogs(logList);
                NpClient.Info_ReleaseScheduleLogs(m_handle, ref logList);
            }
            ShowResult(ret);
        }

        private void btnQueryEvents_Click(object sender, EventArgs e)
        {
            ShowText("***...GetEventLogs...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            Np_EventList eventList = new Np_EventList();
            IntPtr fromTime = IntPtr.Zero;
            IntPtr toTime = IntPtr.Zero;
            IntPtr deviceID = IntPtr.Zero;
            IntPtr eventID = IntPtr.Zero;
            IntPtr id = IntPtr.Zero;

            if (dtspFrom.Value > dtspTo.Value)
            {
                ShowText("\r\n***...StartTime can't large than EndTime...***\r\n");
                return;
            }
            Np_DateTime tempTime = new Np_DateTime();
            fromTime = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Np_DateTime)));
            toTime = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Np_DateTime)));
            ConvertTime(dtspFrom.Value, out tempTime);
            Marshal.StructureToPtr(tempTime, fromTime, false);
            ConvertTime(dtspTo.Value, out tempTime);
            Marshal.StructureToPtr(tempTime, toTime, false);

            if (tbCentralID_PB.Text.Length > 0 && tbLocalID_PB.Text.Length > 0)
            {
                Np_ID id_actually;
                id_actually.centralID = Int32.Parse(tbCentralID_PB.Text);
                id_actually.localID = Int32.Parse(tbLocalID_PB.Text);
                id = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Np_ID)));
                Marshal.StructureToPtr(id_actually, id, false);
            }

            Np_Event_Type tmp = checkEventID(cmbEventID.Text);
            if (Np_Event_Type.Np_EVENT_CODE_BASE != tmp)
            {
                eventID = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)));
                Marshal.StructureToPtr((int)tmp, eventID, false);
            }

            ret = NpClient.Info_QueryEvents(m_handle,
                                            fromTime,
                                            toTime,
                                            deviceID,
                                            id,
                                            eventID,
                                            ref eventList
                                            );

            if (Np_Result.Np_Result_OK == ret)
            {
                ShowEventList(eventList);
                NpClient.Info_ReleaseEvents(m_handle, ref eventList);
            }
            ShowResult(ret);

            Marshal.FreeHGlobal(fromTime);
            Marshal.FreeHGlobal(toTime);
            if (id != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(id);
            }
            if (eventID != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(eventID);
            }
        }

        private void btnOpenRecord_Click(object sender, EventArgs e)
        {
            ShowText("***...OpenRecord...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            Np_DateTime starttime;
            Np_DateTime endtime;
            if (dtspFrom.Value > dtspTo.Value)
            {
                ShowText("\r\n***...StartTime can't large than EndTime...***\r\n");
                return;
            }
            ConvertTime(dtspFrom.Value, out starttime);
            ConvertTime(dtspTo.Value, out endtime);
            ShowTime("start time", starttime);
            ShowTime("end time", endtime);
            ret = NpClient.PlayBack_OpenRecord(
                m_pbPlayer,
                starttime,
                endtime
                );
            ShowResult(ret);
        }

        private void btnPlay_Click(object sender, EventArgs e)
        {
            ShowText("***...Play...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            ret = NpClient.PlayBack_Play(
                m_pbPlayer
                );
            ShowResult(ret); 
        }

        private void btnPause_Click(object sender, EventArgs e)
        {
            ShowText("***...Pause...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            ret = NpClient.PlayBack_Pause(
                m_pbPlayer
                );
            ShowResult(ret); 
        }

        private void btnReverse_Click(object sender, EventArgs e)
        {
            ShowText("***...ReversePlay...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            ret = NpClient.PlayBack_ReversePlay(
                m_pbPlayer
                );
            ShowResult(ret); 
        }

        private void btnForward_Click(object sender, EventArgs e)
        {
            ShowText("***...StepForward...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            ret = NpClient.PlayBack_StepForward(
                m_pbPlayer
                );
            ShowResult(ret); 
        }

        private void btnBackward_Click(object sender, EventArgs e)
        {
            ShowText("***...StepBackward...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            ret = NpClient.PlayBack_StepBackward(
                m_pbPlayer
                );
            ShowResult(ret); 
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            ShowText("***...Next...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            ret = NpClient.PlayBack_Next(
                m_pbPlayer
                );
            ShowResult(ret); 
        }

        private void btnPrevious_Click(object sender, EventArgs e)
        {
            ShowText("***...Previous...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            ret = NpClient.PlayBack_Previous(
                m_pbPlayer
                );
            ShowResult(ret); 
        }

        private void btnSeek_Click(object sender, EventArgs e)
        {
            ShowText("***...Seek...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            Np_DateTime time;
            ConvertTime(dtspFrom.Value, out time);
            ShowTime("Seek Time", time);
            ret = NpClient.PlayBack_Seek(
                m_pbPlayer,
                time
                );
            ShowResult(ret); 
        }

        private void btnSetSpeed_Click(object sender, EventArgs e)
        {
            ShowText("***...SetSpeed...***");
            Np_Result ret = Np_Result.Np_Result_OK;
            ShowText("Speed:");
            ShowText(nspSpeed.Value.ToString());
            ret = NpClient.PlayBack_SetSpeed(
                m_pbPlayer,
                (float)nspSpeed.Value
                );
            ShowResult(ret); 
        }

        private void btnExport_Click(object sender, EventArgs e)
        {
            ShowText("***...ExportVideo...***");
            Np_Result ret = Np_Result.Np_Result_OK;

            if (dtspFrom.Value > dtspTo.Value)
            {
                ShowText("\n***...StartTime shouldn't be larger than EndTime...***\n");
                return;
            }

            if(cmbExportProfile.Items.Count <= 0)
            {
                ShowText("\n***...No profile supported, unable to export video...***\n");
                return;
            }

            Np_ExportContent content = new Np_ExportContent();
            content.id.centralID = m_exptctx.id.centralID = Int32.Parse(tbCentralID_PB.Text);
            content.id.localID = m_exptctx.id.localID = Int32.Parse(tbLocalID_PB.Text);

            ConvertTime(dtspFrom.Value, out content.startTime);
            ConvertTime(dtspTo.Value, out content.endTime);

            for(int i = 0; i < m_pbSessions.Count; ++i)
            {
                int[] keys = new int[m_pbSessions.Count];
                m_pbSessions.Keys.CopyTo(keys, 0);
                if(m_exptctx.id.centralID == m_pbSessions[keys[i]].id.centralID && m_exptctx.id.localID == m_pbSessions[keys[i]].id.localID)
                {
                    m_exptctx.width = content.width = m_pbSessions[keys[i]].width;
                    m_exptctx.height = content.height = m_pbSessions[keys[i]].height;
                    break;
                }
            }

            content.excludeAudio = chbExcludeAudio.Checked;

            ExportProfileItem epi = (ExportProfileItem)cmbExportProfile.SelectedItem;
            try
            {
                FileInfo fi = new FileInfo(tbExportPath.Text);
                if (!fi.Directory.Exists || tbExportPath.Text.EndsWith("\\") || tbExportPath.Text.EndsWith("/"))
                {
                    ShowText("\n***...Should specify a valid file name...***\n");
                    return;
                }

                string fimename_base = fi.FullName.Substring(0, fi.FullName.Length - fi.Extension.Length);
                tbExportPath.Text = FormatExportFilePath(fimename_base, -1, epi.desc);

                ret = NpClient.PlayBack_ExportVideo(m_pbPlayer, content, fimename_base,
                                            epi.format, epi.profile, m_exptcb, IntPtr.Zero, m_osdcb, IntPtr.Zero);
            }
            catch(ArgumentException)
            {
                ShowText("\n***...Should specify a valid file name...***\n");
                return;
            }
            finally
            {
            }
            ShowResult(ret);
            m_bExporting = (Np_Result.Np_Result_OK == ret);
        }

        private void btnExportPath_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Title = "Export Video";
            sfd.Filter = "Videos (*.asf *.avi)|*.asf;*.avi;";
            sfd.ValidateNames = false;
            sfd.FileName = tbExportPath.Text;

            DialogResult result = sfd.ShowDialog(this);
            if (DialogResult.OK == result || DialogResult.Yes == result)
            {
                tbExportPath.Text = sfd.FileName;
            }
        }

        private void btnStopExport_Click(object sender, EventArgs e)
        {
            ShowText("***...StopExport...***");
            Np_Result ret = Np_Result.Np_Result_OK;

            ret = NpClient.PlayBack_StopExport(m_pbPlayer);
            ShowResult(ret);
            pbExportProgress.Value = 0;
            lbExportPercent.Text = "0%";

            FileInfo fi = new FileInfo(tbExportPath.Text);
            FileInfo fi2 = new FileInfo(FormatExportFilePath(fi.FullName.Substring(0, fi.FullName.Length - fi.Extension.Length),
                                        0, cmbExportProfile.Text));
            if (fi2.Exists)
            {
                fi2.Delete();
            }
            m_bExporting = false;
        }

        private void btnSnapShot_Click(object sender, EventArgs e)
        {
            ShowText("***...SnapShot...***");  
            try{
                FileInfo fi = new FileInfo(tbSnapShotPath.Text);
                if (!fi.Directory.Exists || tbSnapShotPath.Text.EndsWith("\\") || tbSnapShotPath.Text.EndsWith("/"))
                {
                    ShowText("\n***...Should specify a valid file name...***\n");
                    return;
                }

                if( !tbSnapShotPath.Text.EndsWith(".bmp", true, System.Globalization.CultureInfo.CurrentUICulture) &&
                    !tbSnapShotPath.Text.EndsWith(".jpg", true, System.Globalization.CultureInfo.CurrentUICulture))
                {
                    tbSnapShotPath.Text = fi.FullName.Substring(0, fi.FullName.Length - fi.Extension.Length) + ".jpg";
                }
            }
            catch(ArgumentException)
            {
                ShowText("\n***...Should specify a valid file name...***\n");
                return;
            }
            finally
            {
            }

            Np_Result ret = Np_Result.Np_Result_NO_DATA;
            if(m_currentFrame != null)
            {
                lock (m_frameLock)
                {
                    int width = m_currentFrame.Width,
                        height = m_currentFrame.Height,
                        len = width * height * 3;
                    Rectangle recVideo = new Rectangle(0, 0, width, height);
                    System.Drawing.Imaging.BitmapData bmp_data = m_currentFrame.LockBits(recVideo,
                                                                                System.Drawing.Imaging.ImageLockMode.WriteOnly,
                                                                                System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                    ret = NpClient.Utility_SaveSnapShotImage(tbSnapShotPath.Text, bmp_data.Scan0, len, width, height);
                    m_currentFrame.UnlockBits(bmp_data);
                }
            }
            ShowResult(ret);

            if(Np_Result.Np_Result_OK == ret)
            {
                if(m_lvSessions.Count > 0)
                {
                    int[] keys = new int[m_lvSessions.Count];
                    m_lvSessions.Keys.CopyTo(keys, 0);
                    Np_ID id = m_lvSessions[keys[m_lvSessions.Count - 1]].id;
                    Np_DateTime now;
                    ConvertTime(DateTime.Now, out now);
                    ret = NpClient.Utility_AddImageWaterMark(tbSnapShotPath.Text, ref now, GetCameraName(id));
                }
                else if(m_pbSessions.Count > 0)
                {
                    int[] keys = new int[m_pbSessions.Count];
                    m_pbSessions.Keys.CopyTo(keys, 0);
                    Np_ID id = m_pbSessions[keys[m_pbSessions.Count - 1]].id;
                    Np_DateTime pb_time;
                    NpClient.PlayBack_GetTime(m_pbPlayer, out pb_time);
                    ret = NpClient.Utility_AddImageWaterMark(tbSnapShotPath.Text, ref pb_time, GetCameraName(id));
                }
            }
        }

        private void btnSnapShotPath_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Title = "SnapShot";
            sfd.Filter = "Images (*.bmp *.jpg)|*.bmp;*.jpg;";
            sfd.ValidateNames = false;
            sfd.FileName = tbSnapShotPath.Text;

            DialogResult result = sfd.ShowDialog(this);
            if (DialogResult.OK == result || DialogResult.Yes == result)
            {
                tbSnapShotPath.Text = sfd.FileName;
            }
        }
    }
}