Inheritance: System.Windows.DependencyObject
 private static void Update(LineInfo trunk, LineInfo inline)
 {
     string sql = "update t_comingrecord set ";
     //主叫
     if (inline != null && inline.CallerPhone != null && !inline.CallerPhone.Equals(""))
     {
         Console.Write("号码" + inline.CallerPhone);
         sql += " callnumber='" + inline.CallerPhone + "',";
     }
     string rectime = trunk.Rectime.ToLocalTime().ToString("yyyyMMdd HH:mm:ss");
     sql += "rectime='" + rectime + "',";
     string handuptime = trunk.Handuptime.ToLocalTime().ToString("yyyyMMdd HH:mm:ss");
     sql += "handuptime='" + handuptime + "',";
     string islink = trunk.Islink;
     sql += "islink='" + islink + "',";
     if (inline != null)
     {
         string inlinenum = inline.Number.ToString();
         sql += " inline = '" + inlinenum + "',";
         string gonghao = inline.Gonghao;
         sql += " gonghao='" + gonghao + "',";
     }
     if (sql.EndsWith(","))
     {
         sql = sql.Substring(0, sql.Length - 1);
     }
     sql += " where id='" + trunk.Id + "'";
     // log.Debug("更新数据" + sql);
     SendMessage(sql);
 }
 //插入来电记录
 private static void Insert(LineInfo line)
 {
     string id = line.Id;
     string comingtime = line.Comingtime.ToLocalTime().ToString("yyyyMMdd HH:mm:ss");
     string trunk = line.Number.ToString();
     string sql = "insert into t_comingrecord(id,comingtime,trunk,islink) values('" + id + "','" + comingtime + "','" + trunk + "','no')";
     //Console.WriteLine("插入数据:" + sql);
     DBHelper.executeNonQuery(sql);
 }
 public void Save(LineInfo trunk, LineInfo inline)
 {
     //如果id为空,说明是心来电,插入,否则更新
     string id = trunk.Id;
     if (id == null || id.Equals(""))
     {
         trunk.Id = Guid.NewGuid().ToString();
         Insert(trunk);
     }
     else
     {
         Update(trunk, inline);
     }
 }
 //来电记录,参数为外线通道
 public static void ComingCall(LineInfo trunk,LineInfo inline)
 {
     try
     {
         if (saveHelper == null)
         {
             loadRecordSave();
         }
         saveHelper.Save(trunk, inline);
     }
     catch (Exception e)
     {
         log.Debug("保存数据失败!");
     }
 }
 /**
  * 检查是否自动接通
  * */
 public bool CheckCanAoutLink(LineInfo line)
 {
     //通道设置有自动接通时间,当前时间在通道时间范围内,转接到该通道
       DateTime now = System.DateTime.Now;
       string nowHM = now.ToString("HH:mm");
       //无开始时间,不自动接通
       if (line.StartHour != null || line.StartHour.Equals(""))
       {
       return false;
       }
       //无结束时间,不自动接通
       if (line.EndHour != null || line.EndHour.Equals(""))
       {
       return false;
       }
       //当前时间在设置的开始结束之间,可接通
       if(nowHM.CompareTo(line.StartHour) > 0 && nowHM.CompareTo(line.EndHour) < 0)
       {
       return true;
       }
       return false;
 }
        //设置监听
        private void setListen(LineInfo line)
        {
            LineInfo anther = null;
            try
            {
                anther = Lines[line.ListenNum];
            }
            catch (Exception e)
            {
                return;
            }
            if (anther != null && anther.State == (ushort)state.CH_CONNECTED)
            {
                int ren = InvokeVcDll.LinkOneToAnother(line.Number, anther.Number);
                log.Debug(line.Number + "监听" + anther.Number + ",返回值:" + ren);
                ren = InvokeVcDll.LinkOneToAnother(line.Number, (ushort)anther.ConnectToLine);
                log.Debug(line.Number + "监听" + anther.ConnectToLine + ",返回值:" + ren);

            }
        }
 //查找空闲内线通道,找不到内线通道返回-1
 private int GetFreeUser(LineInfo line)
 {
     int i =this.ta.Assign(Lines);
     //如果找不到通道,说明都被使用中,判断号码是否是优先接入号码
     if (i == -1)
     {
         string sql = "select * from t_teshuhaoma where phone='" + line.CallerPhone + "'";
         ArrayList result = DBHelper.executeQuery(sql);
         if (result.Count > 0)
         {
             i = getRandom();
             log.Debug("优先接入号码:"+line.CallerPhone +",连接随机通道:"+i);
             LineInfo inLine = Lines[i];
             //强行挂段电话,重置通道
             this.ResetLine(i);
             this.ResetLine(inLine.ConnectToLine);
             //设置内线状态已连接,内线自动连接外线
             inLine.State = (int)state.CH_CHECKSIG;
         }
     }
     return i;
 }
 //得到主叫
 private string getCaller(LineInfo trunk)
 {
     byte[] number = new byte[128];
     InvokeVcDll.GetCallerIDStr(trunk.Number, number);
     string result = Encoding.UTF8.GetString(number);
     result = result.TrimEnd('\0');
     if (result.Length > 8)
     {
         result = result.Substring(8);
     }
     char[] c = {'\0'};
     string[] phone = result.Split(c);
     result = phone[0];
     trunk.CallerPhone = result;
     log.Debug("收外线" + trunk.Number + "主叫号码:" + result);
     return result;
 }
        //主工作方法
        public void yzDoWork(LineInfo line)
        {
            int tmpCode;
            //通道对应的连接通道号
            int tmpCTL = line.ConnectToLine;
            //根据类型处理
            switch (line.Type)
            {
                //内线
                case (int)type.CHTYPE_USER:
                    //未摘机 ,不是空闲,不是响铃
                    if (!line.IsKey && !InvokeVcDll.OffHookDetect(line.Number) && line.State != (int)state.CH_FREE && line.State != (int)state.CH_RINGING)
                    {
                        switch (line.State)
                        {
                            case (int)state.CH_WAITONHOOK:
                                log.Debug("内线" + line.Number + "waitonhook时挂机");
                                InvokeVcDll.StopRecordFile((ushort)line.Number);
                                ResetLine(line.Number);
                                break;
                            case (int)state.CH_CHECKSIG:
                                log.Debug("内线" + line.Number + "checksig等待连接时挂机");
                                InvokeVcDll.FeedPower((ushort)tmpCTL);
                                ResetLine(line.ConnectToLine);
                                ResetLine(line.Number);
                                break;
                            case (int)state.CH_CONNECTED:
                                log.Debug("内线" + line.Number + "连接时挂断");
                                InvokeVcDll.StopRecordFile((ushort)line.Number);
                                int duan = InvokeVcDll.ClearLink(line.Number, (ushort)tmpCTL);
                                log.Debug("断开连接返回值:" + duan);
                                ResetLineInner(line.Number);
                                ResetLine(tmpCTL);
                                break;
                            default:
                                break;
                        }
                    }
                    break;
                case (int)type.CHTYPE_TRUNK:
                   if (InvokeVcDll.Sig_CheckBusy(line.Number) == 1)
                    {
                        switch (line.State)
                        {
                            case (int)state.CH_DIALING:
                                log.Debug("外线" + line.Number + "dialing响铃时时挂断");
                                ResetLine(line.Number);
                                break;
                            case (int)state.CH_CHECKSIG:
                                log.Debug("外线" + line.Number + "checksig等待连接时挂断");
                                this.stopWelcome(line.Number);
                                InvokeVcDll.FeedPower((ushort)line.ConnectToLine);
                                ResetLine(line.ConnectToLine);
                                ResetLine(line.Number);
                                break;
                            case (int)state.CH_CONNECTED:
                                log.Debug("外线" + line.Number + "连接时挂断");
                                InvokeVcDll.StopRecordFile((ushort)line.ConnectToLine);
                                int duan = InvokeVcDll.ClearLink((ushort)tmpCTL, line.Number);
                                log.Debug("通话时挂断返回值:" + duan);
                                int inerline = line.ConnectToLine;
                                ResetLine(line.Number);
                                this.ResetLineInner(inerline);
                                break;
                            case (int)state.CH_GETCAllNUM:
                                int nx = line.ConnectToLine;
                                ResetLine(line.Number);
                                if (nx != -1)
                                {
                                    ResetLine(nx);
                                }
                                break;
                            //播放欢迎语音
                            case (int) state.CH_PlAYWELCOME:
                               int nx1 = line.ConnectToLine;
                                ResetLine(line.Number);
                                if (nx1 != -1)
                                {
                                    ResetLine(nx1);
                                }
                                break;
                            //播放工号
                            case (int)state.CH_PLAYGONGHAO:
                                int nx2 = line.ConnectToLine;
                                ResetLine(line.Number);
                                if (nx2 != -1)
                                {
                                    ResetLine(nx2);
                                }
                                break;
                            //外拨
                            case (int)state.CH_CALLPHONE:
                                log.Debug("内线" + line.ConnectToLine + "外拨"+line.Number+"时,外线拨号时挂断");
                                InvokeVcDll.FeedPower((ushort)line.ConnectToLine);
                                ResetLine(line.Number);
                                break;
                            default:
                                break;
                        }
                    }
                    break;
                default:
                    break;
            }
            //根据状态处理(实际电话处理)
            switch (line.State)
            {
                //空闲状态
                case (int)state.CH_FREE:
                    //监听响铃
                    if (InvokeVcDll.RingDetect(line.Number))
                    {
                        //如果是内线,播放忙音,状态改为摘机
                        if (line.Type == (int)type.CHTYPE_USER)
                        {

                            if(line.State == (int)state.CH_FREE)
                            {
                                log.Debug("内线" + line.Number + "摘机");
                                 InvokeVcDll.InitDtmfBuf(line.Number);
                                 line.State = (int)state.CH_DETECT;
                            }
                           ;
                        }
                        //如果是外线
                        else if (line.Type == (int)type.CHTYPE_TRUNK)
                        {
                            log.Debug("外线" + line.Number + "电话打入");
                            InvokeVcDll.StartSigCheck(line.Number);
                            InvokeVcDll.ResetCallerIDBuffer(line.Number);
                            line.State = (int)state.CH_GETCAllNUM;
                            //设置来电时间
                            line.Comingtime = System.DateTime.Now;
                            //id在comingcall方法内部产生
                            LineRecordHelper.ComingCall(line, null);

                        }
                    }
                    break;

                case (int)state.CH_GETCAllNUM:
                    bool bOffHook = false;
                    if (line.Callertime > 1000)
                    {
                        bOffHook = true;
                    }
                    if (bOffHook)
                    {
                        string zhujiao = getCaller(line);
                        line.State = (int)state.CH_PlAYWELCOME;
                        LineRecordHelper.ComingCall(line, null);
                    }
                    else
                    {
                        line.Callertime += 70;
                    }
                    break;

                //播放欢迎语音
                case (int)state.CH_PlAYWELCOME:
                    InvokeVcDll.OffHook(line.Number);
                    this.playWelcome(line.Number);
                    line.State = (int)state.CH_DIALING;
                    break;
                //查找内线连接
                case (int)state.CH_DIALING:
                    tmpCTL = this.GetFreeUser(line);
                    if (tmpCTL == -1)
                    {
                        //欢迎语音结束,播放坐席忙录音
                        if (InvokeVcDll.CheckPlayEnd(line.Number))
                        {
                            log.Debug("欢迎语音播放完成,播放忙音");
                            this.stopWelcome(line.Number);
                            string weladd = Environment.CurrentDirectory + "\\busy1";
                            InvokeVcDll.StartPlayFile(line.Number, weladd, 0);
                            line.State = (int)state.CH_PLAYBUSY;
                         }
                        break;
                    }
                    Lines[tmpCTL].CallerPhone = line.CallerPhone;
                    InvokeVcDll.FeedRealRing((ushort)tmpCTL);
                    line.ConnectToLine = tmpCTL;
                    Lines[tmpCTL].ConnectToLine = line.Number;
                    line.State = (int)state.CH_CHECKSIG;
                    Lines[tmpCTL].State = (int)state.CH_RINGING;
                    log.Debug("外线" + line.Number + "打入,连接内线" + tmpCTL);
                    LineRecordHelper.ComingCall(line, Lines[tmpCTL]);
                    break;
                //坐席全忙
               case (int)state.CH_PLAYBUSY:
                    if (InvokeVcDll.CheckPlayEnd(line.Number))
                    {
                            log.Debug(line.Number+"忙音播放完,断开");
                            InvokeVcDll.StopPlayFile(line.Number);
                            this.ResetLine(line.Number);
                    }
                    break;
                //等待连接状态
                case (int)state.CH_CHECKSIG:
                    tmpCTL = line.ConnectToLine;
                     //检测内线摘机
                    if (InvokeVcDll.OffHookDetect((ushort)tmpCTL) || Lines[tmpCTL].IsKey)
                    {
                        log.Debug("内线" + tmpCTL + "摘机,与外线" + line.Number + "连通");
                        this.stopWelcome(line.Number);
                        //播放工号
                        log.Debug("播放工号");
                        string weladd = Environment.CurrentDirectory + "\\" + Lines[tmpCTL].Gonghao;
                        InvokeVcDll.StartPlayFile(line.Number, weladd, 0);
                        line.State = (int)state.CH_PLAYGONGHAO;
                        break;
                     }
                    else
                    {
                        LineRecordHelper.ComingCall(line, Lines[tmpCTL]);
                    }
                    break;
                case (int)state.CH_PLAYGONGHAO:
                    tmpCTL = line.ConnectToLine;
                    //检测内线摘机
                    if (InvokeVcDll.OffHookDetect((ushort)tmpCTL) || Lines[tmpCTL].IsKey)
                    {
                        log.Debug("内线" + tmpCTL + "摘机,与外线" + line.Number + "连通");
                        if (InvokeVcDll.CheckPlayEnd(line.Number))
                        {
                            InvokeVcDll.StopPlayFile(line.Number);
                        }
                        else
                        {
                            break;
                        }
                         InvokeVcDll.FeedPower((ushort)tmpCTL);
                        InvokeVcDll.SetLink(line.Number, (ushort)tmpCTL);
                        line.State = (int)state.CH_CONNECTED;
                        Lines[tmpCTL].State = (int)state.CH_CONNECTED;
                        //录音
                        string guid = Guid.NewGuid().ToString();
                        string file = GetSavePath() + guid + ".wav";
                        InvokeVcDll.StartRecordFile((ushort)tmpCTL, file, 1024 * 8 * 60 * 30);
                        Lines[tmpCTL].RecordFile = guid;
                        //设置接通时间
                        line.Rectime = System.DateTime.Now;
                        line.Islink = "yes";

                        LineRecordHelper.ComingCall(line, Lines[tmpCTL]);
                    }
                    else
                    {
                      //  LineRecordHelper.ComingCall(line, Lines[tmpCTL]);
                    }
                    break;
                case (int)state.CH_RINGING:
                    break;
                case (int)state.CH_CONNECTED:
                   if (InvokeVcDll.CheckSendEnd(line.Number))
                    {
                        InvokeVcDll.StartSigCheck(line.Number);
                    }
                    break;
                case (int)state.CH_WAITONHOOK:
                    if (line.Type == (int)type.CHTYPE_TRUNK)
                    {
                        log.Debug("外线" + line.Number + "等待挂机");
                        ResetLine(line.Number);
                    }
                    break;
                //摘机状态
                case (int)state.CH_DETECT:
                    //如果是内线,检测是否挂机
                    if (line.Type == (int)type.CHTYPE_USER)
                    {
                        short code = InvokeVcDll.GetDtmfCode(line.Number);
                        if (code != -1)
                        {
                            log.Debug("内线" + line.Number + "按键" + code);
                            if (line.ListenNum != -1)
                            {
                                InvokeVcDll.ClearOneFromAnother((ushort)line.Number, (ushort)line.ListenNum);
                            }
                            line.ListenNum = ConvertDtmf(code);
                        }
                        InvokeVcDll.StartHangUpDetect(line.Number);
                        if (InvokeVcDll.HangUpDetect(line.Number) == 2)
                        {
                            InvokeVcDll.ClearOneFromAnother((ushort)line.Number, (ushort)line.ListenNum);
                            log.Debug("内线" + line.Number + "挂机111");
                            int num = line.ConnectToLine;
                            ResetLine(line.Number);
                            if (num != -1)
                            {
                                ResetLine(num);
                            }
                        }
                    }
                    break;
                    //外拨
                case (int)state.CH_CALLPHONE:
                    //拨号完成后,建立通道
                    if (InvokeVcDll.CheckSendEnd((ushort)line.Number))
                    {
                        InvokeVcDll.StartSigCheck((ushort)line.Number);
                        InvokeVcDll.StartSigCheck((ushort)line.ConnectToLine);
                        InvokeVcDll.SetLink((ushort)line.Number, (ushort)line.ConnectToLine);
                        //设置为接通
                        line.State = (int)state.CH_CONNECTED;
                        Lines[line.ConnectToLine].State = (int)state.CH_CONNECTED;
                    }
                    break;
                default:
                    break;
            }
        }
        /**
         * 初始化语音通道
         **/
        public void InitLines(ObservableCollection<LineInfo> objs)
        {
            //加载语音通道配置文件
            String currentDir = Environment.CurrentDirectory;
            String path = System.IO.Path.Combine(currentDir, "lines.xml");
            XElement lineConfig = XElement.Load(System.Xml.XmlReader.Create(path));

            ushort TotalLine = InvokeVcDll.CheckValidCh();
            for (int ch = 0; ch < TotalLine; ch++)
            {
                ushort type = InvokeVcDll.CheckChTypeNew(ch);
                LineInfo line = new LineInfo();
                line.Number = (ushort)ch;
                line.Type = type;
                line.ConnectToLine = -1;
                line.State = (int)state.CH_FREE;
                line.CallerPhone = "";
                line.RecordFile = "";
                line.LastTime = System.DateTime.Now;
                line.Comingtime = System.DateTime.Now;
                line.Rectime = System.DateTime.Now; ;
                line.Handuptime = System.DateTime.Now;
                line.Id = "";
                line.Gonghao = "";
                line.IsKey = false;
                line.Islink = "no";
                line.ListenNum = -1;
                //查找配置文件中内容,设置通道属性
                if(lineConfig !=null)
                {
                    XElement element = lineConfig.Elements().Where(e => e.Attribute("num").Value == ch+"").FirstOrDefault();
                    if(element !=null)
                    {
                        //设定通道自动接通的开始和结束小时
                        string shour = (string)element.Attribute("starthour").Value;
                        string ehour = (string)element.Attribute("endhour").Value;
                        line.StartHour =shour;
                        line.EndHour = ehour;
                     }
                 }
                objs.Add(line);
            }
            //给每条通道分配初始语音缓冲区
            if (InvokeVcDll.EnableCard(TotalLine, 1024 * 128) != (long)0)
            {
                InvokeVcDll.FreeDRV();
            }
        }