Modified: freeswitch/branches/joshrivers/mod_managed_update_branch/src/mod/languages/mod_managed/managed/ManagedSession.cs (16628 => 16629)
--- freeswitch/branches/joshrivers/mod_managed_update_branch/src/mod/languages/mod_managed/managed/ManagedSession.cs 2010-02-12 23:02:21 UTC (rev 16628)
+++ freeswitch/branches/joshrivers/mod_managed_update_branch/src/mod/languages/mod_managed/managed/ManagedSession.cs 2010-02-12 23:28:39 UTC (rev 16629)
@@ -45,10 +45,72 @@
// This callback is used for originate
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
- public delegate switch_status_t switch_state_handler_t_delegate(IntPtr sessionPtr);
+ public delegate switch_status_t switch_state_handler_t_delegate(IntPtr sessionPtr);
- public partial class ManagedSession
+ public interface IManagedSession : IDisposable
{
+ int Answer();
+ bool Answered();
+ int Allocated { get; set; }
+ bool BeginAllowThreads();
+ input_callback_state_t CallbackState { get; set; }
+ switch_call_cause_t CallCause { get; set; }
+ SWIGTYPE_p_switch_channel Channel { get; set; }
+ void CheckHangupHook();
+ int CollectDigits(int abs_timeout);
+ int CollectDigits(int digit_timeout, int abs_timeout);
+ Func<Char, TimeSpan, string> DtmfReceivedFunction { get; set; }
+ void Destroy();
+ bool EndAllowThreads();
+ Func<Native.Event, string> EventReceivedFunction { get; set; }
+ void Execute(string app, string data);
+ uint Flags { get; set; }
+ int FlushEvents();
+ int FlushDigits();
+ switch_input_args_t GetCallbackArguments();
+ string GetState();
+ string GetUuid();
+ string GetDigits(int maxdigits, string terminators, int timeout);
+ string GetDigits(int maxdigits, string terminators, int timeout, int interdigit);
+ SWIGTYPE_p_void GetPrivate(string var);
+ string GetVariable(string var);
+ string GetXmlCdr();
+ void Hangup(string cause);
+ string HangupCause();
+ Action HangupFunction { get; set; }
+ void HangupState();
+ switch_channel_state_t HookState { get; set; }
+ SWIGTYPE_p_switch_core_session InternalSession { get; set; }
+ bool IsAvailable { get; }
+ bool MediaReady();
+ bool Originate(CoreSession aLegSession, string destination, TimeSpan timeout);
+ string PlayAndGetDigits(int min_digits, int max_digits, int max_tries, int timeout, string terminators, string audio_files, string bad_input_audio_files, string digits_regex, string var_name);
+ int PreAnswer();
+ void QueuePrivateEvent(IEvent sendME);
+ string Read(int min_digits, int max_digits, string prompt_audio_file, int timeout, string valid_terminators);
+ bool Ready();
+ int RecordFile(string file_name, int time_limit, int silence_threshold, int silence_hits);
+ int SetAutoHangup(bool val);
+ void SetPrivate(string var, SWIGTYPE_p_void val);
+ void SetVariable(string var, string val);
+ void Say(string tosay, string module_name, string say_type, string say_method);
+ void SayPhrase(string phrase_name, string phrase_data, string phrase_lang);
+ void SetTtsParameters(string tts_name, string voice_name);
+ int Speak(string text);
+ int StreamFile(string file, int starting_sample_count);
+ int Sleep(int ms, int sync);
+ void SendEvent(Event sendME);
+ void SetEventData(Event e);
+ int Transfer(string extension, string dialplan, string context);
+ string TextToSpeechEngine { get; set; }
+ string TextToSpeechVoice { get; set; }
+ Guid Uuid { get; }
+ string UuidString { get; set; }
+ ManagedSession.IChannelVariables Variables { get; }
+ void WaitForAnswer(CoreSession calling_session);
+ }
+ public partial class ManagedSession : IManagedSession
+ {
// SWITCH_DECLARE(void) InitManagedSession(ManagedSession *session, MonoObject *dtmfDelegate, MonoObject *hangupDelegate)
[DllImport("mod_managed.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
static extern void InitManagedSession(IntPtr sessionPtr, DtmfCallback dtmfDelegate, CdeclAction hangupDelegate);
@@ -56,7 +118,8 @@
/// <summary>Initializes the native ManagedSession. Called after Originate completes successfully .</summary>
internal void Initialize()
{
- if (allocated == 0) {
+ if (Allocated == 0)
+ {
throw new InvalidOperationException("Cannot initialize a ManagedSession until it is allocated (originated successfully).");
}
// P/Invoke generated function pointers stick around until the delegate is collected
@@ -77,11 +140,13 @@
void hangupCallback()
{
Log.WriteLine(LogLevel.Debug, "AppFunction is in hangupCallback.");
- try {
+ try
+ {
var f = HangupFunction;
if (f != null) f();
}
- catch (Exception ex) {
+ catch (Exception ex)
+ {
Log.WriteLine(LogLevel.Warning, "Exception in hangupCallback: {0}", ex.ToString());
}
}
@@ -92,43 +157,54 @@
string inputCallback(IntPtr input, Native.switch_input_type_t inputType)
{
- try {
- switch (inputType) {
+ try
+ {
+ switch (inputType)
+ {
case FreeSWITCH.Native.switch_input_type_t.SWITCH_INPUT_TYPE_DTMF:
- using (var dtmf = new Native.switch_dtmf_t(input, false)) {
+ using (var dtmf = new Native.switch_dtmf_t(input, false))
+ {
return dtmfCallback(dtmf);
}
case FreeSWITCH.Native.switch_input_type_t.SWITCH_INPUT_TYPE_EVENT:
- using (var swevt = new Native.switch_event(input, false)) {
+ using (var swevt = new Native.switch_event(input, false))
+ {
return eventCallback(swevt);
}
default:
return "";
}
- } catch (Exception ex) {
+ }
+ catch (Exception ex)
+ {
Log.WriteLine(LogLevel.Error, "InputCallback threw exception: " + ex.ToString());
return "-ERR InputCallback Exception: " + ex.Message;
}
}
- string dtmfCallback(Native.switch_dtmf_t dtmf) {
+ string dtmfCallback(Native.switch_dtmf_t dtmf)
+ {
var f = DtmfReceivedFunction;
- return f == null ? ""
+ return f == null ? ""
: f(((char)(byte)dtmf.digit), TimeSpan.FromMilliseconds(dtmf.duration));
}
- string eventCallback(Native.switch_event swevt) {
- using (var evt = new FreeSWITCH.Native.Event(swevt, 0)) {
+ string eventCallback(Native.switch_event swevt)
+ {
+ using (var evt = new FreeSWITCH.Native.Event(swevt, 0))
+ {
var f = EventReceivedFunction;
- return f == null ? ""
+ return f == null ? ""
: f(evt);
}
}
[Obsolete("Use static Originate method.", false)]
- public bool Originate(CoreSession aLegSession, string destination, TimeSpan timeout) {
+ public bool Originate(CoreSession aLegSession, string destination, TimeSpan timeout)
+ {
var res = 0 == this.originate(aLegSession, destination, (int)timeout.TotalMilliseconds, null);
- if (res) {
+ if (res)
+ {
this.Initialize();
}
return res;
@@ -139,18 +215,22 @@
// The delegate needs to be stored so it doesn't get GC'd, so we can't just return GetFunctionPointerForDelegate right away.
/// <summary>Wraps a nice handler into a delegate suitable for reverse P/Invoke. This only currently works well for hangup/reporting handlers.</summary>
- public static switch_state_handler_t_delegate CreateStateHandlerDelegate(Action<ManagedSession> handler) {
+ public static switch_state_handler_t_delegate CreateStateHandlerDelegate(Action<ManagedSession> handler)
+ {
// We create a ManagedSession on top of the session so callbacks can use it "nicely"
// Then we sort of dispose it.
- switch_state_handler_t_delegate del = ptr => {
- using (var sess = new ManagedSession(new SWIGTYPE_p_switch_core_session(ptr, false))) {
+ switch_state_handler_t_delegate del = ptr =>
+ {
+ using (var sess = new ManagedSession(new SWIGTYPE_p_switch_core_session(ptr, false)))
+ {
handler(sess);
return switch_status_t.SWITCH_STATUS_SUCCESS;
}
};
return del;
}
- public static SWIGTYPE_p_f_p_switch_core_session__switch_status_t WrapStateHandlerDelegate(switch_state_handler_t_delegate del) {
+ public static SWIGTYPE_p_f_p_switch_core_session__switch_status_t WrapStateHandlerDelegate(switch_state_handler_t_delegate del)
+ {
return new SWIGTYPE_p_f_p_switch_core_session__switch_status_t(Marshal.GetFunctionPointerForDelegate(del), false);
}
@@ -162,15 +242,18 @@
switch_state_handler_table originate_table;
GCHandle originate_keepalive_handle; // Make sure the B Leg is not collected and disposed until we run ondestroy
- switch_status_t originate_ondestroy_method(IntPtr channelPtr) {
+ switch_status_t originate_ondestroy_method(IntPtr channelPtr)
+ {
// CS_DESTROY lets the bleg be collected
// and frees originate_table memory
// Note that this (bleg ManagedSession) is invalid
// to touch right now - the unmanaged memory has already been free'd
- if (this.originate_keepalive_handle.IsAllocated) {
+ if (this.originate_keepalive_handle.IsAllocated)
+ {
this.originate_keepalive_handle.Free(); // GC can now collect this bleg
}
- if (this.originate_table != null) {
+ if (this.originate_table != null)
+ {
this.originate_table.Dispose();
this.originate_table = null;
}
@@ -181,12 +264,15 @@
/// Performs originate. Returns ManagedSession on success, null on failure.
/// onHangup is called as a state handler, after the channel is truly hungup (CS_REPORTING).
/// </summary>
- public static ManagedSession OriginateHandleHangup(CoreSession aLegSession, string destination, TimeSpan timeout, Action<ManagedSession> onHangup) {
+ public static ManagedSession OriginateHandleHangup(CoreSession aLegSession, string destination, TimeSpan timeout, Action<ManagedSession> onHangup)
+ {
var bleg = new ManagedSession();
bleg.originate_ondestroy_delegate = bleg.originate_ondestroy_method;
- bleg.originate_onhangup_delegate = CreateStateHandlerDelegate(sess_b => {
- if (onHangup != null) {
+ bleg.originate_onhangup_delegate = CreateStateHandlerDelegate(sess_b =>
+ {
+ if (onHangup != null)
+ {
onHangup(sess_b);
}
});
@@ -196,35 +282,199 @@
bleg.originate_table.flags = (int)switch_state_handler_flag_t.SSH_FLAG_STICKY;
var res = 0 == bleg.originate(aLegSession, destination, (int)timeout.TotalSeconds, bleg.originate_table);
bleg.originate_keepalive_handle = GCHandle.Alloc(bleg, GCHandleType.Normal); // Prevent GC from eating the bleg
- if (res) {
+ if (res)
+ {
bleg.Initialize();
return bleg;
- } else {
+ }
+ else
+ {
// Dispose to free the lock
// The bleg lives on with its unmanaged memory freed
// Until CS_DESTROY gets called
- bleg.Dispose();
+ bleg.Dispose();
return null;
}
}
// Convenience
- public bool IsAvailable {
+ public bool IsAvailable
+ {
get { return this.Ready(); }
}
- public Guid Uuid {
- get {
- if (allocated == 0) throw new InvalidOperationException("Session has not been initialized.");
+ public Guid Uuid
+ {
+ get
+ {
+ if (Allocated == 0) throw new InvalidOperationException("Session has not been initialized.");
return new Guid(this.GetUuid());
}
}
- public switch_call_cause_t CallCause {
- get {
- if (allocated == 0) throw new InvalidOperationException("Session has not been initialized.");
- return freeswitch.switch_channel_get_cause(this.channel);
+ public switch_call_cause_t CallCause
+ {
+ get
+ {
+ if (Allocated == 0) throw new InvalidOperationException("Session has not been initialized.");
+ return freeswitch.switch_channel_get_cause(this.Channel);
}
+ set
+ {
+ if (Allocated == 0) throw new InvalidOperationException("Session has not been initialized.");
+ base.CallCause = value;
+ }
}
+
+ public void QueuePrivateEvent(IEvent sendME)
+ {
+ Event sendEE = sendME as Event;
+ if (sendEE == null) { return; }
+ base.QueuePrivateEvent(sendEE);
+ }
}
+
+ public interface IEvent : IDisposable
+ {
+ switch_event InternalEvent { get; set; }
+ string serialized_string { get; set; }
+ int mine { get; set; }
+ string Serialize(string format);
+ bool SetPriority(switch_priority_t priority);
+ string GetHeader(string header_name);
+ string GetBody();
+ string GetEventType();
+ bool AddBody(string value);
+ bool AddHeader(string header_name, string value);
+ bool DeleteHeader(string header_name);
+ bool Fire();
+ IEnumerable<string> HeaderNames();
+ }
+ public partial class Event : IEvent
+ {
+ public IEnumerable<string> HeaderNames()
+ {
+ switch_event_header header = this.InternalEvent.headers;
+ while (header != null)
+ {
+ yield return header.name;
+ header = header.next;
+ }
+ }
+
+ public class EventClassStrings
+ {
+ public static readonly string SWITCH_EVENT_CUSTOM = "CUSTOM";
+ public static readonly string SWITCH_EVENT_CLONE = "CLONE";
+ public static readonly string SWITCH_EVENT_CHANNEL_CREATE = "CHANNEL_CREATE";
+ public static readonly string SWITCH_EVENT_CHANNEL_DESTROY = "CHANNEL_DESTROY";
+ public static readonly string SWITCH_EVENT_CHANNEL_STATE = "CHANNEL_STATE";
+ public static readonly string SWITCH_EVENT_CHANNEL_ANSWER = "CHANNEL_ANSWER";
+ public static readonly string SWITCH_EVENT_CHANNEL_HANGUP = "CHANNEL_HANGUP";
+ public static readonly string SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE = "CHANNEL_HANGUP_COMPLETE";
+ public static readonly string SWITCH_EVENT_CHANNEL_EXECUTE = "CHANNEL_EXECUTE";
+ public static readonly string SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE = "CHANNEL_EXECUTE_COMPLETE";
+ public static readonly string SWITCH_EVENT_CHANNEL_BRIDGE = "CHANNEL_BRIDGE";
+ public static readonly string SWITCH_EVENT_CHANNEL_UNBRIDGE = "CHANNEL_UNBRIDGE";
+ public static readonly string SWITCH_EVENT_CHANNEL_PROGRESS = "CHANNEL_PROGRESS";
+ public static readonly string SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA = "CHANNEL_PROGRESS_MEDIA";
+ public static readonly string SWITCH_EVENT_CHANNEL_OUTGOING = "CHANNEL_OUTGOING";
+ public static readonly string SWITCH_EVENT_CHANNEL_PARK = "CHANNEL_PARK";
+ public static readonly string SWITCH_EVENT_CHANNEL_UNPARK = "CHANNEL_UNPARK";
+ public static readonly string SWITCH_EVENT_CHANNEL_APPLICATION = "CHANNEL_APPLICATION";
+ public static readonly string SWITCH_EVENT_CHANNEL_ORIGINATE = "CHANNEL_ORIGINATE";
+ public static readonly string SWITCH_EVENT_CHANNEL_UUID = "CHANNEL_UUID";
+ public static readonly string SWITCH_EVENT_API = "API";
+ public static readonly string SWITCH_EVENT_LOG = "LOG";
+ public static readonly string SWITCH_EVENT_INBOUND_CHAN = "INBOUND_CHAN";
+ public static readonly string SWITCH_EVENT_OUTBOUND_CHAN = "OUTBOUND_CHAN";
+ public static readonly string SWITCH_EVENT_STARTUP = "STARTUP";
+ public static readonly string SWITCH_EVENT_SHUTDOWN = "SHUTDOWN";
+ public static readonly string SWITCH_EVENT_PUBLISH = "PUBLISH";
+ public static readonly string SWITCH_EVENT_UNPUBLISH = "UNPUBLISH";
+ public static readonly string SWITCH_EVENT_TALK = "TALK";
+ public static readonly string SWITCH_EVENT_NOTALK = "NOTALK";
+ public static readonly string SWITCH_EVENT_SESSION_CRASH = "SESSION_CRASH";
+ public static readonly string SWITCH_EVENT_MODULE_LOAD = "MODULE_LOAD";
+ public static readonly string SWITCH_EVENT_MODULE_UNLOAD = "MODULE_UNLOAD";
+ public static readonly string SWITCH_EVENT_DTMF = "DTMF";
+ public static readonly string SWITCH_EVENT_MESSAGE = "MESSAGE";
+ public static readonly string SWITCH_EVENT_PRESENCE_IN = "PRESENCE_IN";
+ public static readonly string SWITCH_EVENT_NOTIFY_IN = "NOTIFY_IN";
+ public static readonly string SWITCH_EVENT_PRESENCE_OUT = "PRESENCE_OUT";
+ public static readonly string SWITCH_EVENT_PRESENCE_PROBE = "PRESENCE_PROBE";
+ public static readonly string SWITCH_EVENT_MESSAGE_WAITING = "MESSAGE_WAITING";
+ public static readonly string SWITCH_EVENT_MESSAGE_QUERY = "MESSAGE_QUERY";
+ public static readonly string SWITCH_EVENT_ROSTER = "ROSTER";
+ public static readonly string SWITCH_EVENT_CODEC = "CODEC";
+ public static readonly string SWITCH_EVENT_BACKGROUND_JOB = "BACKGROUND_JOB";
+ public static readonly string SWITCH_EVENT_DETECTED_SPEECH = "DETECTED_SPEECH";
+ public static readonly string SWITCH_EVENT_DETECTED_TONE = "DETECTED_TONE";
+ public static readonly string SWITCH_EVENT_PRIVATE_COMMAND = "PRIVATE_COMMAND";
+ public static readonly string SWITCH_EVENT_HEARTBEAT = "HEARTBEAT";
+ public static readonly string SWITCH_EVENT_TRAP = "TRAP";
+ public static readonly string SWITCH_EVENT_ADD_SCHEDULE = "ADD_SCHEDULE";
+ public static readonly string SWITCH_EVENT_DEL_SCHEDULE = "DEL_SCHEDULE";
+ public static readonly string SWITCH_EVENT_EXE_SCHEDULE = "EXE_SCHEDULE";
+ public static readonly string SWITCH_EVENT_RE_SCHEDULE = "RE_SCHEDULE";
+ public static readonly string SWITCH_EVENT_RELOADXML = "RELOADXML";
+ public static readonly string SWITCH_EVENT_NOTIFY = "NOTIFY";
+ public static readonly string SWITCH_EVENT_SEND_MESSAGE = "SEND_MESSAGE";
+ public static readonly string SWITCH_EVENT_RECV_MESSAGE = "RECV_MESSAGE";
+ public static readonly string SWITCH_EVENT_REQUEST_PARAMS = "REQUEST_PARAMS";
+ public static readonly string SWITCH_EVENT_CHANNEL_DATA = "CHANNEL_DATA";
+ public static readonly string SWITCH_EVENT_GENERAL = "GENERAL";
+ public static readonly string SWITCH_EVENT_COMMAND = "COMMAND";
+ public static readonly string SWITCH_EVENT_SESSION_HEARTBEAT = "SESSION_HEARTBEAT";
+ public static readonly string SWITCH_EVENT_CLIENT_DISCONNECTED = "CLIENT_DISCONNECTED";
+ public static readonly string SWITCH_EVENT_SERVER_DISCONNECTED = "SERVER_DISCONNECTED";
+ public static readonly string SWITCH_EVENT_SEND_INFO = "SEND_INFO";
+ public static readonly string SWITCH_EVENT_RECV_INFO = "RECV_INFO";
+ public static readonly string SWITCH_EVENT_CALL_SECURE = "CALL_SECURE";
+ public static readonly string SWITCH_EVENT_NAT = "NAT";
+ public static readonly string SWITCH_EVENT_RECORD_START = "RECORD_START";
+ public static readonly string SWITCH_EVENT_RECORD_STOP = "RECORD_STOP";
+ public static readonly string SWITCH_EVENT_CALL_UPDATE = "CALL_UPDATE";
+ public static readonly string SWITCH_EVENT_ALL = "ALL";
+ }
+ }
+
+ public interface IManagedEventConsumer
+ {
+ IEvent Pop(bool block);
+ }
+ public class ManagedEventConsumer : IDisposable, IManagedEventConsumer
+ {
+ private EventConsumer _eventConsumer;
+ public ManagedEventConsumer(string eventClass, string EventSubclass)
+ {
+ this._eventConsumer = new EventConsumer(eventClass, EventSubclass);
+ }
+
+ public IEvent Pop(bool block)
+ {
+ if (block)
+ {
+ return this._eventConsumer.pop(1);
+ }
+ else
+ {
+ return this._eventConsumer.pop(0);
+ }
+ }
+
+ public void Dispose()
+ {
+ this._eventConsumer.Dispose();
+ }
+ }
+
+
+ public interface IApi : IDisposable
+ {
+ string Execute(string command, string data);
+ string ExecuteString(string command);
+ string getTime();
+ }
+ public partial class Api : IApi { }
}