[Freeswitch-svn] [commit] r8245 - in freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk: EventWatcher FreeSwitchEventSocket FreeSwitchEventSocket/ChannelEvents FreeSwitchEventSocket/Commands FreeSwitchEventSocket/Events FreeSwitchEventSocket/Ivr IvrSocket
Author: verifier Date: Fri May 2 07:23:27 2008 New Revision: 8245 Added: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/SendEventCmd.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Ivr/DtmfEventArgs.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Ivr/IvrQueue.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Ivr/PrivateWaitDtmf.cs Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/EventWatcher/CallManager.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/ChannelEvents/EventChannelExecute.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/ChannelEvents/EventChannelExecuteComplete.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/AnyCommand.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/AuthCommand.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/CmdBase.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/CommandReply.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/ExecuteJavascript.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/GetVariable.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/Originate.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/Playback.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/SetVariable.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/EventSocket.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Events/EventBase.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Events/EventMessageWaiting.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/FreeSwitch.EventSocket.csproj freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Ivr/IvrInterface.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/IvrSocket/Program.cs freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/IvrSocket/Voicemail.cs Log: Been working on the IvrInterface. Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/EventWatcher/CallManager.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/EventWatcher/CallManager.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/EventWatcher/CallManager.cs Fri May 2 07:23:27 2008 @@ -222,20 +222,20 @@ { GetVariableReply gvr = (GetVariableReply) reply; if (!gvr.Success) - Debug.WriteLine("OnBridgeCallId " + reply.ErrCode); + Debug.WriteLine("OnBridgeCallId " + reply.ErrorMessage); string otherChannelId = (string) command.ContextData; SetVariable sv = new SetVariable(otherChannelId, "gate_callid", gvr.Value); - sv.OnReply += OnCallIdReply; + sv.ReplyReceived += OnCallIdReply; _eventMgr.Send(sv); - command.OnReply -= OnBridgeCallId; + command.ReplyReceived -= OnBridgeCallId; } private void OnCallIdReply(CmdBase command, CommandReply reply) { if (!reply.Success) - Debug.WriteLine("OnCallIdReply " + reply.ErrCode); - command.OnReply -= OnCallIdReply; + Debug.WriteLine("OnCallIdReply " + reply.ErrorMessage); + command.ReplyReceived -= OnCallIdReply; } #region Nested type: ExtensionMapper Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/ChannelEvents/EventChannelExecute.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/ChannelEvents/EventChannelExecute.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/ChannelEvents/EventChannelExecute.cs Fri May 2 07:23:27 2008 @@ -1,10 +1,32 @@ -using System; -using System.Collections.Generic; -using System.Text; - namespace FreeSwitch.EventSocket { public class EventChannelExecute : EventChannelState { + private string _appName; + private string _arguments; + + public string AppName + { + get { return _appName; } + set { _appName = value; } + } + + public string Arguments + { + get { return _arguments; } + set { _arguments = value; } + } + + public override bool ParseCommand(string name, string value) + { + if (name == "application") + AppName = value; + else if (name == "application-data") + Arguments = value; + else + return base.ParseCommand(name, value); + + return true; + } } } Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/ChannelEvents/EventChannelExecuteComplete.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/ChannelEvents/EventChannelExecuteComplete.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/ChannelEvents/EventChannelExecuteComplete.cs Fri May 2 07:23:27 2008 @@ -2,6 +2,32 @@ { public class EventChannelExecuteComplete : EventChannelState { + private string _appName; + private string _arguments; + + public string AppName + { + get { return _appName; } + set { _appName = value; } + } + + public string Arguments + { + get { return _arguments; } + set { _arguments = value; } + } + + public override bool ParseCommand(string name, string value) + { + if (name == "application") + AppName = value; + else if (name == "application-data") + Arguments = value; + else + return base.ParseCommand(name, value); + + return true; + } } } Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/AnyCommand.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/AnyCommand.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/AnyCommand.cs Fri May 2 07:23:27 2008 @@ -28,7 +28,7 @@ else { CommandReply reply = new CommandReply(false); - reply.ErrCode = dataToParse; + reply.ErrorMessage = dataToParse; return reply; } } Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/AuthCommand.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/AuthCommand.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/AuthCommand.cs Fri May 2 07:23:27 2008 @@ -26,7 +26,7 @@ else { CommandReply reply = new CommandReply(false); - reply.ErrCode = dataToParse; + reply.ErrorMessage = dataToParse; return reply; } } Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/CmdBase.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/CmdBase.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/CmdBase.cs Fri May 2 07:23:27 2008 @@ -8,7 +8,7 @@ public abstract class CmdBase { - public event ReplyHandler OnReply; + public event ReplyHandler ReplyReceived; private object _contextData; @@ -35,16 +35,21 @@ public virtual void HandleReply(CommandReply reply) { // a command is only invoked once. - if (OnReply != null) + if (ReplyReceived != null) { - OnReply(this, reply); - OnReply = null; + ReplyReceived(this, reply); + ReplyReceived = null; } } public virtual CommandReply CreateReply(string dataToParse) { - return null; + if (string.IsNullOrEmpty(dataToParse.Trim())) + return new CommandReply(false); + + CommandReply reply = new CommandReply(dataToParse.Trim()[0] == '+'); + reply.ErrorMessage = dataToParse; + return reply; } public override string ToString() Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/CommandReply.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/CommandReply.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/CommandReply.cs Fri May 2 07:23:27 2008 @@ -6,7 +6,7 @@ public class CommandReply { private bool _success; - private string _errCode; + private string _ErrorMessage; public CommandReply(bool success) { @@ -18,10 +18,10 @@ get { return _success; } } - public string ErrCode + public string ErrorMessage { - get { return _errCode; } - set { _errCode = value; } + get { return _ErrorMessage; } + set { _ErrorMessage = value; } } public override string ToString() @@ -29,7 +29,7 @@ if (_success) return "Success"; else - return "Failed: " + _errCode; + return "Failed: " + _ErrorMessage; } } } Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/ExecuteJavascript.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/ExecuteJavascript.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/ExecuteJavascript.cs Fri May 2 07:23:27 2008 @@ -47,7 +47,7 @@ else { CommandReply reply = new CommandReply(false); - reply.ErrCode = dataToParse; + reply.ErrorMessage = dataToParse; return reply; } } Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/GetVariable.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/GetVariable.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/GetVariable.cs Fri May 2 07:23:27 2008 @@ -39,7 +39,7 @@ else { GetVariableReply reply = new GetVariableReply(false, string.Empty); - reply.ErrCode = dataToParse; + reply.ErrorMessage = dataToParse; return reply; } } Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/Originate.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/Originate.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/Originate.cs Fri May 2 07:23:27 2008 @@ -97,9 +97,9 @@ { OriginateReply reply = new OriginateReply(false, string.Empty); if (nameValue.Length > 1) - reply.ErrCode = nameValue[1]; + reply.ErrorMessage = nameValue[1]; else - reply.ErrCode = dataToParse; + reply.ErrorMessage = dataToParse; return reply; } } Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/Playback.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/Playback.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/Playback.cs Fri May 2 07:23:27 2008 @@ -6,6 +6,7 @@ public class PlaybackCmd : SendMsg { private readonly string _fileName; + private readonly string _dtmfAbort = string.Empty; /// <summary> /// @@ -21,6 +22,12 @@ _fileName = fileName; } + public PlaybackCmd(string uuid, string fileName, string dtmfAbort) : base(uuid) + { + _fileName = fileName; + _dtmfAbort = dtmfAbort; + } + public override string Command { get { return "playback"; } @@ -30,5 +37,10 @@ { get { return _fileName; } } + + public string DtmfAbort + { + get { return _dtmfAbort; } + } } } Added: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/SendEventCmd.cs ============================================================================== --- (empty file) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/SendEventCmd.cs Fri May 2 07:23:27 2008 @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FreeSwitch.EventSocket.Commands +{ + public class SendEventCmd : CmdBase + { + private EventBase _event; + + /// <summary> + /// + /// </summary> + /// <param name="evt">Note that all events have NOT being developed to be sent, only to be received.</param> + public SendEventCmd(EventBase evt) + { + _event = evt; + } + + + public override string Command + { + get { return "sendevent " + _event.Name + "\n"; } + } + + public override string Arguments + { + get { return _event.ToString(); } + } + } +} Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/SetVariable.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/SetVariable.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Commands/SetVariable.cs Fri May 2 07:23:27 2008 @@ -25,7 +25,17 @@ public override string Arguments { - get { return _channelId + " " + _name + " " + _value; } + get { return _channelId + " " + Name + " " + Value; } + } + + public string Name + { + get { return _name; } + } + + public string Value + { + get { return _value; } } public override CommandReply CreateReply(string dataToParse) @@ -35,7 +45,7 @@ else { CommandReply reply = new CommandReply(false); - reply.ErrCode = dataToParse; + reply.ErrorMessage = dataToParse; return reply; } } Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/EventSocket.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/EventSocket.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/EventSocket.cs Fri May 2 07:23:27 2008 @@ -79,7 +79,6 @@ } catch (SocketException) { - Console.WriteLine("EventSocket: Connect failed"); HandleDisconnect(); } } @@ -88,8 +87,6 @@ { lock (_lockobj) { - Console.WriteLine("EventSocket.TryConnect: Connecting to " + _hostName + ":" + _port); - _socket.Connect(_hostName, _port); if (_stream == null) _stream = new NetworkStream(_socket, false); @@ -167,9 +164,7 @@ { try { - Console.WriteLine("EventSocket.Write: Trying to connect eventsocket."); TryConnect(); - Console.WriteLine("EventSocket.Write: Connected."); } catch (SocketException) { @@ -189,7 +184,7 @@ if (msg.ContentType == "auth/request") { AuthCommand cmd = new AuthCommand(_password); - cmd.OnReply += OnAuthed; + cmd.ReplyReceived += OnAuthed; _commands.Enqueue(cmd); Write(cmd + "\n\n"); } @@ -199,7 +194,6 @@ if (_commands.Count > 0) { CmdBase cmd = _commands.Dequeue(); - Console.WriteLine("Reply to " + cmd.GetType().Name + ": " + msg.Body); cmd.HandleReply(cmd.CreateReply(msg.Body)); } else @@ -285,14 +279,11 @@ EventSocket client = (EventSocket) state; try { - Console.WriteLine("EventSocket.Timer: Trying to connect eventsocket."); client.TryConnect(); Console.WriteLine("EventSocket.Timer: Connected."); } - catch (SocketException err) - { - Console.WriteLine("Eventsocket.TryConnect: " + err.Message); - } + catch (SocketException) + {} } } } \ No newline at end of file Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Events/EventBase.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Events/EventBase.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Events/EventBase.cs Fri May 2 07:23:27 2008 @@ -19,7 +19,27 @@ public string Name { - get { return m_name; } + get + { + lock (this) + { + if (string.IsNullOrEmpty(m_name)) + { + string name = GetType().Name.Substring(5); //remove (Event) + m_name = string.Empty; + m_name += char.ToUpper(name[0]); + for (int i = 1; i < name.Length; ++i) + { + if (char.IsUpper(name[i])) + m_name += '_'; + else + m_name += char.ToUpper(name[i]); + } + } + } + + return m_name; + } set { m_name = value; } } Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Events/EventMessageWaiting.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Events/EventMessageWaiting.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Events/EventMessageWaiting.cs Fri May 2 07:23:27 2008 @@ -8,6 +8,18 @@ private int _totalMessages; private int _totalUrgentMessages; + public EventMessageWaiting() + { + + } + + public EventMessageWaiting(string account, int newMessages, int totalMessages) + { + _account = account; + _newMessages = newMessages; + _totalMessages = totalMessages; + } + /// <summary> /// Messages are for this account /// </summary> Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/FreeSwitch.EventSocket.csproj ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/FreeSwitch.EventSocket.csproj (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/FreeSwitch.EventSocket.csproj Fri May 2 07:23:27 2008 @@ -35,10 +35,6 @@ <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Xml" /> - <Reference Include="Tiny.Net, Version=1.0.0.1, Culture=neutral, PublicKeyToken=15480ee9e0247fcb, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>..\..\..\dlls\Debug\Tiny.Net.dll</HintPath> - </Reference> </ItemGroup> <ItemGroup> <Compile Include="ChannelEvents\EventChannelApplication.cs" /> @@ -65,12 +61,16 @@ <Compile Include="Commands\ParkCmd.cs" /> <Compile Include="Commands\Playback.cs" /> <Compile Include="Commands\RecordCmd.cs" /> + <Compile Include="Commands\SendEventCmd.cs" /> <Compile Include="Commands\SendMsg.cs" /> <Compile Include="Commands\SetVariable.cs" /> <Compile Include="Commands\SleepCmd.cs" /> <Compile Include="EventManager.cs" /> <Compile Include="ChannelEvents\EventDtmfStatus.cs" /> + <Compile Include="Ivr\DtmfEventArgs.cs" /> <Compile Include="Ivr\IvrInterface.cs" /> + <Compile Include="Ivr\IvrQueue.cs" /> + <Compile Include="Ivr\PrivateWaitDtmf.cs" /> <Compile Include="PlainEventMsg.cs" /> <Compile Include="EventParser.cs" /> <Compile Include="Events.cs" /> @@ -118,6 +118,7 @@ </Target> --> <PropertyGroup> - <PostBuildEvent>copy $(TargetPath) $(SolutionDir)..\..\dlls\$(ConfigurationName)</PostBuildEvent> + <PostBuildEvent> + </PostBuildEvent> </PropertyGroup> </Project> \ No newline at end of file Added: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Ivr/DtmfEventArgs.cs ============================================================================== --- (empty file) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Ivr/DtmfEventArgs.cs Fri May 2 07:23:27 2008 @@ -0,0 +1,44 @@ +using System; + +namespace FreeSwitch.EventSocket.Ivr +{ + + public class DtmfEventArgs : EventArgs + { + private string _dtmf; + private string _dtmfCopy; + + public DtmfEventArgs(string dtmf) + { + _dtmf = dtmf; + _dtmfCopy = (string)_dtmf.Clone(); + } + + /// <summary> + /// You cannot remove digits from the buffer (since it's a copy of the real buffer). + /// </summary> + /// <seealso cref="RemoveDigits"/> + public string Dtmf + { + get { return _dtmfCopy; } + } + + /// <summary> + /// Remove digits from the real buffer. + /// </summary> + /// <param name="count">number of digits to remove.</param> + public void RemoveDigits(int count) + { + lock (_dtmf) + { + if (count > _dtmf.Length) + _dtmf = string.Empty; + else + _dtmf = _dtmf.Remove(0, count); + _dtmfCopy = (string)_dtmf.Clone(); + } + } + } + + public delegate void DtmfHandler(object source, DtmfEventArgs args); +} Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Ivr/IvrInterface.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Ivr/IvrInterface.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Ivr/IvrInterface.cs Fri May 2 07:23:27 2008 @@ -8,16 +8,19 @@ { public const string AllDigits = "*#0123456789"; private readonly string _uuid; - private readonly string _baseSoundPath = "sounds\\"; + private string _baseSoundPath = "sounds\\"; private string _dtmf = string.Empty; private EventManager _mgr; public event DtmfHandler DtmfReceived; - private readonly int _dtmfWaitCount = 0; - private ManualResetEvent _dtmfWaitEvent; + private int _dtmfWaitCount = 0; private bool _abortSpeechOnDtmf; private bool _answered; private IvrInterfaceHandler _handler = null; private string _lastAbortDigits = "*"; + private int _defaultTimeout = 10000; + private readonly ManualResetEvent _dtmfTimeout = new ManualResetEvent(false); + private IvrQueue _queue; + public IvrInterface(EventManager mgr, string uuid) { @@ -26,6 +29,7 @@ if (string.IsNullOrEmpty(uuid)) throw new ArgumentNullException("uuid"); + _queue = new IvrQueue(mgr); _mgr = mgr; mgr.EventReceived += OnEvent; _uuid = uuid; @@ -54,34 +58,64 @@ set { _abortSpeechOnDtmf = value; } } + /// <summary> + /// True if IVR call have been answered. + /// </summary> public bool Answered { get { return _answered; } } + /// <summary> + /// Number of seconds to wait on DTMF + /// </summary> + public int DefaultTimeout + { + get { return _defaultTimeout; } + set { _defaultTimeout = value; } + } + + /// <summary> + /// Relative path under FreeSWITCH to where the sound files resides + /// </summary> + /// <remarks>default is "sounds\"</remarks> + public string BaseSoundPath + { + get { return _baseSoundPath; } + set { _baseSoundPath = value; } + } + private void OnEvent(EventBase receivedEvent) { + if (!receivedEvent.IsChannelEvent) + return; + + ChannelEvent channelEvent = (ChannelEvent) receivedEvent; + if (channelEvent.UniqueId != _uuid) + return; + if (receivedEvent is EventChannelAnswer) { _answered = true; } -/* else if (receivedEvent is EventDtmfStatus) - { - // Let's always dequeue dtmf. - EventDtmfStatus evt = (EventDtmfStatus) receivedEvent; - if (evt.UniqueId == _uuid) - _mgr.Send(new GetDtmfCmd(_uuid, evt.Count)); - }*/ else if (receivedEvent is EventDtmf) { EventDtmf evt = (EventDtmf) receivedEvent; - lock (_dtmf) - _dtmf += evt.Digit; - if (_dtmfWaitCount >= _dtmf.Length) - _dtmfWaitEvent.Set(); + Console.WriteLine("DTMF Event: " + evt.Digit); + if (_queue.GotDtmf(evt.Digit)) + { + lock (_dtmf) + _dtmf += evt.Digit; + + if (_dtmfWaitCount != 0 && _dtmf.Length >= _dtmfWaitCount) + { + Console.WriteLine("Got all DTMF: " + _dtmfWaitCount + "/" + _dtmf.Length); + _dtmfTimeout.Set(); + } - if (DtmfReceived != null) - DtmfReceived(this, new DtmfEventArgs(_dtmf)); + if (DtmfReceived != null) + DtmfReceived(this, new DtmfEventArgs(_dtmf)); + } } else if (receivedEvent is EventChannelDestroy || receivedEvent is EventChannelHangup) { @@ -91,6 +125,16 @@ _mgr = null; } } + else if (receivedEvent is EventChannelExecute) + { + EventChannelExecute exec = (EventChannelExecute)receivedEvent; + _queue.Execute(exec); + } + else if (receivedEvent is EventChannelExecuteComplete) + { + EventChannelExecuteComplete exec = (EventChannelExecuteComplete)receivedEvent; + _queue.ExecuteComplete(exec); + } } /// <summary> @@ -104,15 +148,26 @@ { if (_mgr == null) return string.Empty; - if (_dtmfWaitEvent != null) - throw new InvalidOperationException("Already waiting on an event."); + + lock (_dtmf) + { + if (_dtmfWaitCount > 0) + throw new InvalidOperationException("Already waiting on an event."); + _dtmfWaitCount = 1; + _dtmfTimeout.Reset(); + } if (_dtmf.Length < count) { - _dtmfWaitEvent = new ManualResetEvent(false); - if (!_dtmfWaitEvent.WaitOne(timeout * 1000, true)) + if (_queue.CommandRunning) + _queue.Add(new PrivateWaitDtmf(OnDtmfTimeout, timeout)); + + _dtmfWaitCount = count - _dtmf.Length; + if (!_dtmfTimeout.WaitOne(timeout, true)) { + Console.WriteLine("Didn't get any DTMF: " + _dtmf); _dtmf = string.Empty; + _dtmfWaitCount = 0; return string.Empty; } } @@ -122,14 +177,54 @@ if (_dtmf.Length >= count) { string dtmf = _dtmf.Substring(0, count); - _dtmf = _dtmf.Remove(count); + if (_dtmf.Length == count) + _dtmf = string.Empty; + else + _dtmf = _dtmf.Remove(count); + _dtmfWaitCount = 0; return dtmf; } } + _dtmfWaitCount = 0; return string.Empty; } + private void OnDtmfTimeout(PrivateWaitDtmf dtmf) + { + dtmf.Dispose(); + _dtmfTimeout.Set(); + } + + /// <summary> + /// Wait on dtmf. + /// </summary> + /// <param name="count">Number of digits to get</param> + /// <remarks>You can also used the Dtmf event if you want to use asynchrounous programming.</remarks> + /// <seealso cref="DtmfReceived"/> + /// <seealso cref="DefaultTimeout"/> + public string GetDtmf(int count) + { + return GetDtmf(count, _defaultTimeout); + } + + /// <summary> + /// Play a sound file + /// </summary> + /// <param name="path">Path to sound file.</param> + /// <seealso cref="AllDigits"/> + /// <remarks>Prepends <see cref="BaseSoundPath"/> to path.</remarks> + public void Play(string path) + { + Play(path, AllDigits); + } + + /// <summary> + /// Play a sound file + /// </summary> + /// <param name="path">Path to sound file.</param> + /// <param name="digitsToAbortOn">DTMF digits that can abort speech.</param> + /// <remarks>Prepends <see cref="BaseSoundPath"/> to path.</remarks> public void Play(string path, string digitsToAbortOn) { if (_mgr == null) @@ -144,69 +239,61 @@ _lastAbortDigits = digitsToAbortOn; } - _mgr.Send(new PlaybackCmd(_uuid, _baseSoundPath + path)); + _queue.Add(new PlaybackCmd(_uuid, GetSoundPath(path, false), digitsToAbortOn)); } - public void Record(string path, bool stop, int limit) - { - if (_mgr == null) - return; - _mgr.Send(new RecordCmd(_uuid, _baseSoundPath + path, stop, limit)); - } - public void Record(string path, int limit) - { - if (_mgr == null) - return; - _mgr.Send(new RecordCmd(_uuid, _baseSoundPath + path, limit)); - } - public void Sleep(int ms) + /// <summary> + /// Record a sound file + /// </summary> + /// <param name="path">Where to store the sound</param> + /// <param name="limit">Maximum number of seconds that can be recorded.</param> + /// <param name="stop">stop an ongoing recording</param> + public void Record(string path, int limit, bool stop) { if (_mgr == null) return; - _mgr.Send(new SleepCmd(_uuid, ms)); - } - } - public class DtmfEventArgs : EventArgs - { - private string _dtmf; - private string _dtmfCopy; + _queue.Add(new RecordCmd(_uuid, GetSoundPath(path, true), stop, limit)); + } - public DtmfEventArgs(string dtmf) + /// <summary> + /// Record a sound file + /// </summary> + /// <param name="path">Where to store the sound</param> + /// <param name="limit">Maximum number of seconds that can be recorded.</param> + public void Record(string path, int limit) { - _dtmf = dtmf; - _dtmfCopy = (string) _dtmf.Clone(); + Record(path, limit, false); } /// <summary> - /// You cannot remove digits from the buffer (since it's a copy of the real buffer). + /// This method can be used to build paths for different languages and such. /// </summary> - /// <seealso cref="RemoveDigits"/> - public string Dtmf + /// <param name="fileName">soundfile</param> + /// <param name="isRecording">path is to a file being recorded</param> + /// <returns>Path to sound file</returns> + protected virtual string GetSoundPath(string fileName, bool isRecording) { - get { return _dtmfCopy; } + return BaseSoundPath + fileName; } /// <summary> - /// Remove digits from the real buffer. + /// Tell script to sleep for a while. /// </summary> - /// <param name="count">number of digits to remove.</param> - public void RemoveDigits(int count) + /// <param name="ms">number of milliseconds</param> + public void Sleep(int ms) { - lock (_dtmf) - { - if (count > _dtmf.Length) - _dtmf = string.Empty; - else - _dtmf = _dtmf.Remove(0, count); - _dtmfCopy = (string)_dtmf.Clone(); - } + if (_mgr == null) + return; + + _queue.Add(new SleepCmd(_uuid, ms)); } + + } - public delegate void DtmfHandler(object source, DtmfEventArgs args); public delegate void IvrInterfaceHandler(IvrInterface app); -} +} \ No newline at end of file Added: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Ivr/IvrQueue.cs ============================================================================== --- (empty file) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Ivr/IvrQueue.cs Fri May 2 07:23:27 2008 @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using FreeSwitch.EventSocket.Commands; + +namespace FreeSwitch.EventSocket.Ivr +{ + internal class IvrQueue + { + private readonly Queue<CmdBase> _items = new Queue<CmdBase>(); + private readonly EventManager _mgr; + private CmdBase _currentCommand; + + public IvrQueue(EventManager mgr) + { + if (mgr == null) + throw new ArgumentNullException("mgr"); + + _mgr = mgr; + } + + public bool CommandRunning + { + get { return _currentCommand != null; } + } + + public void Add(CmdBase cmd) + { + lock (_items) + _items.Enqueue(cmd); + } + + public void Execute(EventChannelExecute evt) + { + } + + public void ExecuteComplete(EventChannelExecuteComplete evt) + { + Console.WriteLine(evt.AppName + "(" + evt.Arguments + ") is done."); + + if (_currentCommand != null && evt.AppName != _currentCommand.Command) + { + Console.WriteLine("Executed something that is not ours: " + _currentCommand.Command); + return; + } + + // run next command + lock (_items) + { + _currentCommand = null; + + if (_items.Count > 0) + { + // check if next cmd is waiting on dtmf, then trigger it to start. + if (_items.Peek().Command == "privdtmf") + ((PrivateWaitDtmf) _items.Peek()).Trigger(); + + SendNextCommand(); + } + } + } + + /// <summary> + /// a DTMF was pressed. Validate it towards the queue + /// </summary> + /// <param name="digit"></param> + /// <returns>true if it can be processed, false if not.</returns> + public bool GotDtmf(char digit) + { + bool isValid = true; + + lock (_items) + { + // dequeue all play commands if correct digit is pressed. + while (_items.Count > 0) + { + if (_items.Peek().GetType() == typeof (SetVariable)) + { + Console.WriteLine("Is SetVariable"); + SetVariable var = (SetVariable) _items.Peek(); + string digits = string.Empty; + digits += digit; + if (var.Name == "playback_terminators" ) + { + if (var.Value.Contains(digits)) + { + _items.Dequeue(); + if (_items.Count > 0 && _items.Peek().GetType() == typeof(PlaybackCmd)) + _items.Dequeue(); + } + else + isValid = false; //digit was not one of the terminators. skip it. + } + } + else if (_items.Peek().GetType() == typeof(PlaybackCmd)) + { + Console.WriteLine("Is PlaybackCmd"); + PlaybackCmd cmd = (PlaybackCmd)_items.Peek(); + string digits = string.Empty; + digits += digit; + if (cmd.DtmfAbort.Contains(digits)) + _items.Dequeue(); + else + { + isValid = false; //digit was not one of the terminators, skip it. + break; + } + } + else + break; + } + + // and dequeue the dtmf command. + if (_items.Count > 0 && _items.Peek().GetType() == typeof(PrivateWaitDtmf)) + ((PrivateWaitDtmf) _items.Dequeue()).Dispose(); + } + + return isValid; + } + + private static void OnCommandReply(CmdBase command, CommandReply reply) + { + command.ReplyReceived -= OnCommandReply; + if (!reply.Success) + { + Console.WriteLine("Command failed: " + reply.ErrorMessage); + } + } + + public CmdBase Peek() + { + lock (_items) + { + return _items.Peek(); + } + } + + public CmdBase Pop() + { + lock (_items) + { + return _items.Dequeue(); + } + } + + private void SendNextCommand() + { + lock (_items) + { + if (_currentCommand != null) + throw new InvalidOperationException("A command is already running."); + + _currentCommand = _items.Dequeue(); + } + + _currentCommand.ReplyReceived += OnCommandReply; + _mgr.Send(_currentCommand); + } + } +} \ No newline at end of file Added: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Ivr/PrivateWaitDtmf.cs ============================================================================== --- (empty file) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/Ivr/PrivateWaitDtmf.cs Fri May 2 07:23:27 2008 @@ -0,0 +1,70 @@ +using System; +using System.Threading; +using FreeSwitch.EventSocket.Commands; + +namespace FreeSwitch.EventSocket.Ivr +{ + internal delegate void DtmfTimeoutHandler(PrivateWaitDtmf dtmf); + + internal class PrivateWaitDtmf : CmdBase, IDisposable + { + private Timer _timer; + private readonly int _waitTime; + private readonly DtmfTimeoutHandler _handler; + + /// <summary> + /// DTMF timeouts should be counted AFTER a phrase has been said. + /// this small command allows us to start the timer when so. + /// </summary> + /// <param name="handler">Method that will be signalled when the DTMF command goes on timeout.</param> + /// <param name="time">Number of seconds to wait on input.</param> + public PrivateWaitDtmf(DtmfTimeoutHandler handler, int time) + { + if (handler == null) + throw new ArgumentNullException("handler"); + if (time == 0) + throw new ArgumentException("time cannot be 0.", "time"); + if (time < 100) + time *= 1000; + _waitTime = time; + _handler = handler; + } + + public override string Command + { + get { return "privdtmf"; } + } + + public override string Arguments + { + get { return _waitTime.ToString(); } + } + + public void Trigger() + { + _timer = new Timer(OnTimeout, null, _waitTime, Timeout.Infinite); + } + + private void OnTimeout(object state) + { + _timer.Dispose(); + _timer = null; + _handler(this); + } + + #region IDisposable Members + + ///<summary> + ///Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + ///</summary> + ///<filterpriority>2</filterpriority> + public void Dispose() + { + if (_timer != null) + _timer.Dispose(); + _timer = null; + } + + #endregion + } +} Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/IvrSocket/Program.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/IvrSocket/Program.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/IvrSocket/Program.cs Fri May 2 07:23:27 2008 @@ -1,5 +1,7 @@ using System; +using System.Threading; using FreeSwitch.EventSocket; +using FreeSwitch.EventSocket.Commands; namespace IvrSocket { @@ -12,17 +14,13 @@ mgr.EventReceived += IvrManager; mgr.Subscribe(Event.All); mgr.Start("localhost"); + Thread.Sleep(1000); + //mgr.Send(new SendEventCmd(new EventMessageWaiting("jonas@192.168.0.58", 1, 2))); Console.ReadLine(); } private static void IvrManager(EventBase receivedEvent) { - Console.WriteLine(receivedEvent.Name); - if (receivedEvent is ChannelEvent) - { - ChannelEvent evt = (ChannelEvent) receivedEvent; - Console.WriteLine(evt.Name + ": " + evt.UniqueId); - } if (receivedEvent is EventChannelAnswer) { EventChannelAnswer answer = (EventChannelAnswer)receivedEvent; Modified: freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/IvrSocket/Voicemail.cs ============================================================================== --- freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/IvrSocket/Voicemail.cs (original) +++ freeswitch/trunk/scripts/contrib/verifier/EventSocket/trunk/IvrSocket/Voicemail.cs Fri May 2 07:23:27 2008 @@ -21,6 +21,10 @@ private void OnIvr(IvrInterface app) { _ivr.Play("sv\\system\\record_after_beep.wav", IvrInterface.AllDigits); + _ivr.Play("sv\\system\\record_after_beep.wav", IvrInterface.AllDigits); + _ivr.Play("sv\\system\\record_after_beep.wav", "2"); + string dtmf = _ivr.GetDtmf(4); + Console.WriteLine("Got DTMF: " + dtmf); //_ivr.Sleep(5000); //_ivr.Record("voicemails\\" + Guid.NewGuid() + ".wav", 60); }
participants (1)
-
Freeswitch SVN