<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][16667] </title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=16667">16667</a></dd>
<dt>Author</dt> <dd>joshrivers</dd>
<dt>Date</dt> <dd>2010-02-16 19:07:57 -0600 (Tue, 16 Feb 2010)</dd>
</dl>
<h3>Log Message</h3>
<pre>Merging changes to branch.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#freeswitchbranchesjoshriversmod_managed_simplified_branchsrcmodlanguagesmod_managedfreeswitchi">freeswitch/branches/joshrivers/mod_managed_simplified_branch/src/mod/languages/mod_managed/freeswitch.i</a></li>
<li><a href="#freeswitchbranchesjoshriversmod_managed_simplified_branchsrcmodlanguagesmod_managedmanagedChannelVariablescs">freeswitch/branches/joshrivers/mod_managed_simplified_branch/src/mod/languages/mod_managed/managed/ChannelVariables.cs</a></li>
<li><a href="#freeswitchbranchesjoshriversmod_managed_simplified_branchsrcmodlanguagesmod_managedmanagedManagedSessioncs">freeswitch/branches/joshrivers/mod_managed_simplified_branch/src/mod/languages/mod_managed/managed/ManagedSession.cs</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchbranchesjoshriversmod_managed_simplified_branchsrcmodlanguagesmod_managedfreeswitchi"></a>
<div class="modfile"><h4>Modified: freeswitch/branches/joshrivers/mod_managed_simplified_branch/src/mod/languages/mod_managed/freeswitch.i (16666 => 16667)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/joshrivers/mod_managed_simplified_branch/src/mod/languages/mod_managed/freeswitch.i        2010-02-17 01:01:13 UTC (rev 16666)
+++ freeswitch/branches/joshrivers/mod_managed_simplified_branch/src/mod/languages/mod_managed/freeswitch.i        2010-02-17 01:07:57 UTC (rev 16667)
</span><span class="lines">@@ -76,6 +76,7 @@
</span><span class="cx"> %typemap(csclassmodifiers) ManagedSession "public partial class"
</span><span class="cx"> %typemap(csclassmodifiers) Event "public partial class"
</span><span class="cx"> %typemap(csclassmodifiers) Stream "public partial class"
</span><ins>+%typemap(csclassmodifiers) API "public partial class"
</ins><span class="cx"> %newobject EventConsumer::pop;
</span><span class="cx"> %newobject Session;
</span><span class="cx"> %newobject CoreSession;
</span><span class="lines">@@ -148,6 +149,34 @@
</span><span class="cx"> %rename (Speak) CoreSession::speak;
</span><span class="cx"> %rename (SetTtsParameters) CoreSession::set_tts_parms;
</span><span class="cx"> %rename (SetAutoHangup) CoreSession::setAutoHangup;
</span><ins>+%rename (Flags) CoreSession::flags;
+%rename (Channel) CoreSession::channel;
+%rename (Allocated) CoreSession::allocated;
+%rename (CallbackState) CoreSession::cb_state;
+%rename (UuidString) CoreSession::uuid;
+%rename (TextToSpeechEngine) CoreSession::tts_name;
+%rename (TextToSpeechVoice) CoreSession::voice_name;
+%rename (PreAnswer) CoreSession::preAnswer;
+%rename (HangupState) CoreSession::hangupState;
+%rename (HangupCause) CoreSession::hangupCause;
+%rename (GetState) CoreSession::getState;
+%rename (Destroy) CoreSession::destroy;
+%rename (Read) CoreSession::read;
+%rename (Sleep) CoreSession::sleep;
+%rename (FlushEvents) CoreSession::flushEvents;
+%rename (FlushDigits) CoreSession::flushDigits;
+%rename (Answered) CoreSession::answered;
+%rename (MediaReady) CoreSession::mediaReady;
+%rename (WaitForAnswer) CoreSession::waitForAnswer;
+%rename (SendEvent) CoreSession::sendEvent;
+%rename (QueuePrivateEvent) CoreSession::queuePrivateEvent;
+%rename (SetEventData) CoreSession::setEventData;
+%rename (GetXmlCdr) CoreSession::getXMLCDR;
+%rename (BeginAllowThreads) CoreSession::begin_allow_threads;
+%rename (EndAllowThreads) CoreSession::end_allow_threads;
+%rename (GetCallbackArguments) CoreSession::get_cb_args;
+%rename (CheckHangupHook) CoreSession::check_hangup_hook;
+%rename (CallCause) CoreSession::cause;
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> %rename (Serialize) Event::serialize;
</span></span></pre></div>
<a id="freeswitchbranchesjoshriversmod_managed_simplified_branchsrcmodlanguagesmod_managedmanagedChannelVariablescs"></a>
<div class="modfile"><h4>Modified: freeswitch/branches/joshrivers/mod_managed_simplified_branch/src/mod/languages/mod_managed/managed/ChannelVariables.cs (16666 => 16667)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/joshrivers/mod_managed_simplified_branch/src/mod/languages/mod_managed/managed/ChannelVariables.cs        2010-02-17 01:01:13 UTC (rev 16666)
+++ freeswitch/branches/joshrivers/mod_managed_simplified_branch/src/mod/languages/mod_managed/managed/ChannelVariables.cs        2010-02-17 01:07:57 UTC (rev 16667)
</span><span class="lines">@@ -66,7 +66,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> ChannelVariables _variables; // Set on ManagedSession init
</span><del>- public ChannelVariables Variables {
</del><ins>+ public IChannelVariables Variables {
</ins><span class="cx"> get {
</span><span class="cx"> if (_variables == null) {
</span><span class="cx"> _variables = new ChannelVariables(this);
</span><span class="lines">@@ -75,8 +75,49 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ public interface IChannelVariables
+ {
+ IDictionary<string, string> GetAllVariables();
+ bool BypassMedia { get; set; }
+ DateTime CreatedTime { get; }
+ DateTime? AnsweredTime { get; }
+ DateTime? HangupTime { get; }
+ DateTime? ProgressTime { get; }
+ DateTime? ProgressMediaTime { get; }
+ DateTime? TransferTime { get; }
+ string SofiaProfileName { get; }
+ string SipCallID { get; }
+ string SipReceivedIP { get; }
+ short? SipReceivedPort { get; }
+ string SipViaProtocolString { get; }
+ string SipFromUser { get; }
+ string SipFromUriString { get; }
+ string SipFromHost { get; }
+ string SipReqUser { get; }
+ string SipReqUriString { get; }
+ string SipReqHost { get; }
+ string SipToUser { get; }
+ string SipToUriString { get; }
+ string SipToHost { get; }
+ string SipContactUser { get; }
+ string SipContactUriString { get; }
+ string SipContactHost { get; }
+ short? SipContactPort { get; }
+ string SipDestinationUrlString { get; }
+ int? SipTermStatus { get; }
+ int? SipTermCause { get; }
+ string SwitchRSdp { get; }
+ string SwitchMSdp { get; }
+ string SipHangupPhrase { get; }
+ string ProtoSpecificHangupCause { get; }
+ string HangupCauseString { get; }
+ int? HangupCauseQ850 { get; }
+ string OriginateDispositionString { get; }
+ Native.switch_call_direction_t CallDirection { get; }
+ }
</ins><span class="cx"> /// <summary>Strongly typed access to common variables</summary>
</span><del>- public class ChannelVariables {
</del><ins>+ public class ChannelVariables : IChannelVariables
+ {
</ins><span class="cx"> readonly ManagedSession sess;
</span><span class="cx"> internal ChannelVariables(ManagedSession session) {
</span><span class="cx"> this.sess = session;
</span><span class="lines">@@ -84,12 +125,12 @@
</span><span class="cx">
</span><span class="cx"> public IDictionary<string, string> GetAllVariables() {
</span><span class="cx"> var dic = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
</span><del>- var evt = Native.freeswitch.switch_channel_variable_first(sess.channel);
</del><ins>+ var evt = Native.freeswitch.switch_channel_variable_first(sess.Channel);
</ins><span class="cx"> while(evt != null) {
</span><span class="cx"> dic.Add(evt.name, evt.value);
</span><span class="cx"> evt = evt.next;
</span><span class="cx"> }
</span><del>- Native.freeswitch.switch_channel_variable_last(sess.channel);
</del><ins>+ Native.freeswitch.switch_channel_variable_last(sess.Channel);
</ins><span class="cx"> return dic;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="freeswitchbranchesjoshriversmod_managed_simplified_branchsrcmodlanguagesmod_managedmanagedManagedSessioncs"></a>
<div class="modfile"><h4>Modified: freeswitch/branches/joshrivers/mod_managed_simplified_branch/src/mod/languages/mod_managed/managed/ManagedSession.cs (16666 => 16667)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/branches/joshrivers/mod_managed_simplified_branch/src/mod/languages/mod_managed/managed/ManagedSession.cs        2010-02-17 01:01:13 UTC (rev 16666)
+++ freeswitch/branches/joshrivers/mod_managed_simplified_branch/src/mod/languages/mod_managed/managed/ManagedSession.cs        2010-02-17 01:07:57 UTC (rev 16667)
</span><span class="lines">@@ -45,10 +45,72 @@
</span><span class="cx">
</span><span class="cx"> // This callback is used for originate
</span><span class="cx"> [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
</span><del>- public delegate switch_status_t switch_state_handler_t_delegate(IntPtr sessionPtr);
</del><ins>+ public delegate switch_status_t switch_state_handler_t_delegate(IntPtr sessionPtr);
</ins><span class="cx">
</span><del>- public partial class ManagedSession
</del><ins>+ public interface IManagedSession : IDisposable
</ins><span class="cx"> {
</span><ins>+ 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
+ {
</ins><span class="cx"> // SWITCH_DECLARE(void) InitManagedSession(ManagedSession *session, MonoObject *dtmfDelegate, MonoObject *hangupDelegate)
</span><span class="cx"> [DllImport("mod_managed.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
</span><span class="cx"> static extern void InitManagedSession(IntPtr sessionPtr, DtmfCallback dtmfDelegate, CdeclAction hangupDelegate);
</span><span class="lines">@@ -56,7 +118,8 @@
</span><span class="cx"> /// <summary>Initializes the native ManagedSession. Called after Originate completes successfully .</summary>
</span><span class="cx"> internal void Initialize()
</span><span class="cx"> {
</span><del>- if (allocated == 0) {
</del><ins>+ if (Allocated == 0)
+ {
</ins><span class="cx"> throw new InvalidOperationException("Cannot initialize a ManagedSession until it is allocated (originated successfully).");
</span><span class="cx"> }
</span><span class="cx"> // P/Invoke generated function pointers stick around until the delegate is collected
</span><span class="lines">@@ -77,11 +140,13 @@
</span><span class="cx"> void hangupCallback()
</span><span class="cx"> {
</span><span class="cx"> Log.WriteLine(LogLevel.Debug, "AppFunction is in hangupCallback.");
</span><del>- try {
</del><ins>+ try
+ {
</ins><span class="cx"> var f = HangupFunction;
</span><span class="cx"> if (f != null) f();
</span><span class="cx"> }
</span><del>- catch (Exception ex) {
</del><ins>+ catch (Exception ex)
+ {
</ins><span class="cx"> Log.WriteLine(LogLevel.Warning, "Exception in hangupCallback: {0}", ex.ToString());
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -92,43 +157,54 @@
</span><span class="cx">
</span><span class="cx"> string inputCallback(IntPtr input, Native.switch_input_type_t inputType)
</span><span class="cx"> {
</span><del>- try {
- switch (inputType) {
</del><ins>+ try
+ {
+ switch (inputType)
+ {
</ins><span class="cx"> case FreeSWITCH.Native.switch_input_type_t.SWITCH_INPUT_TYPE_DTMF:
</span><del>- using (var dtmf = new Native.switch_dtmf_t(input, false)) {
</del><ins>+ using (var dtmf = new Native.switch_dtmf_t(input, false))
+ {
</ins><span class="cx"> return dtmfCallback(dtmf);
</span><span class="cx"> }
</span><span class="cx"> case FreeSWITCH.Native.switch_input_type_t.SWITCH_INPUT_TYPE_EVENT:
</span><del>- using (var swevt = new Native.switch_event(input, false)) {
</del><ins>+ using (var swevt = new Native.switch_event(input, false))
+ {
</ins><span class="cx"> return eventCallback(swevt);
</span><span class="cx"> }
</span><span class="cx"> default:
</span><span class="cx"> return "";
</span><span class="cx"> }
</span><del>- } catch (Exception ex) {
</del><ins>+ }
+ catch (Exception ex)
+ {
</ins><span class="cx"> Log.WriteLine(LogLevel.Error, "InputCallback threw exception: " + ex.ToString());
</span><span class="cx"> return "-ERR InputCallback Exception: " + ex.Message;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- string dtmfCallback(Native.switch_dtmf_t dtmf) {
</del><ins>+ string dtmfCallback(Native.switch_dtmf_t dtmf)
+ {
</ins><span class="cx"> var f = DtmfReceivedFunction;
</span><del>- return f == null ? ""
</del><ins>+ return f == null ? ""
</ins><span class="cx"> : f(((char)(byte)dtmf.digit), TimeSpan.FromMilliseconds(dtmf.duration));
</span><span class="cx"> }
</span><span class="cx">
</span><del>- string eventCallback(Native.switch_event swevt) {
- using (var evt = new FreeSWITCH.Native.Event(swevt, 0)) {
</del><ins>+ string eventCallback(Native.switch_event swevt)
+ {
+ using (var evt = new FreeSWITCH.Native.Event(swevt, 0))
+ {
</ins><span class="cx"> var f = EventReceivedFunction;
</span><del>- return f == null ? ""
</del><ins>+ return f == null ? ""
</ins><span class="cx"> : f(evt);
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> [Obsolete("Use static Originate method.", false)]
</span><del>- public bool Originate(CoreSession aLegSession, string destination, TimeSpan timeout) {
</del><ins>+ public bool Originate(CoreSession aLegSession, string destination, TimeSpan timeout)
+ {
</ins><span class="cx"> var res = 0 == this.originate(aLegSession, destination, (int)timeout.TotalMilliseconds, null);
</span><del>- if (res) {
</del><ins>+ if (res)
+ {
</ins><span class="cx"> this.Initialize();
</span><span class="cx"> }
</span><span class="cx"> return res;
</span><span class="lines">@@ -139,18 +215,22 @@
</span><span class="cx"> // The delegate needs to be stored so it doesn't get GC'd, so we can't just return GetFunctionPointerForDelegate right away.
</span><span class="cx">
</span><span class="cx"> /// <summary>Wraps a nice handler into a delegate suitable for reverse P/Invoke. This only currently works well for hangup/reporting handlers.</summary>
</span><del>- public static switch_state_handler_t_delegate CreateStateHandlerDelegate(Action<ManagedSession> handler) {
</del><ins>+ public static switch_state_handler_t_delegate CreateStateHandlerDelegate(Action<ManagedSession> handler)
+ {
</ins><span class="cx"> // We create a ManagedSession on top of the session so callbacks can use it "nicely"
</span><span class="cx"> // Then we sort of dispose it.
</span><del>- switch_state_handler_t_delegate del = ptr => {
- using (var sess = new ManagedSession(new SWIGTYPE_p_switch_core_session(ptr, false))) {
</del><ins>+ switch_state_handler_t_delegate del = ptr =>
+ {
+ using (var sess = new ManagedSession(new SWIGTYPE_p_switch_core_session(ptr, false)))
+ {
</ins><span class="cx"> handler(sess);
</span><span class="cx"> return switch_status_t.SWITCH_STATUS_SUCCESS;
</span><span class="cx"> }
</span><span class="cx"> };
</span><span class="cx"> return del;
</span><span class="cx"> }
</span><del>- public static SWIGTYPE_p_f_p_switch_core_session__switch_status_t WrapStateHandlerDelegate(switch_state_handler_t_delegate del) {
</del><ins>+ public static SWIGTYPE_p_f_p_switch_core_session__switch_status_t WrapStateHandlerDelegate(switch_state_handler_t_delegate del)
+ {
</ins><span class="cx"> return new SWIGTYPE_p_f_p_switch_core_session__switch_status_t(Marshal.GetFunctionPointerForDelegate(del), false);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -162,15 +242,18 @@
</span><span class="cx"> switch_state_handler_table originate_table;
</span><span class="cx"> GCHandle originate_keepalive_handle; // Make sure the B Leg is not collected and disposed until we run ondestroy
</span><span class="cx">
</span><del>- switch_status_t originate_ondestroy_method(IntPtr channelPtr) {
</del><ins>+ switch_status_t originate_ondestroy_method(IntPtr channelPtr)
+ {
</ins><span class="cx"> // CS_DESTROY lets the bleg be collected
</span><span class="cx"> // and frees originate_table memory
</span><span class="cx"> // Note that this (bleg ManagedSession) is invalid
</span><span class="cx"> // to touch right now - the unmanaged memory has already been free'd
</span><del>- if (this.originate_keepalive_handle.IsAllocated) {
</del><ins>+ if (this.originate_keepalive_handle.IsAllocated)
+ {
</ins><span class="cx"> this.originate_keepalive_handle.Free(); // GC can now collect this bleg
</span><span class="cx"> }
</span><del>- if (this.originate_table != null) {
</del><ins>+ if (this.originate_table != null)
+ {
</ins><span class="cx"> this.originate_table.Dispose();
</span><span class="cx"> this.originate_table = null;
</span><span class="cx"> }
</span><span class="lines">@@ -181,12 +264,15 @@
</span><span class="cx"> /// Performs originate. Returns ManagedSession on success, null on failure.
</span><span class="cx"> /// onHangup is called as a state handler, after the channel is truly hungup (CS_REPORTING).
</span><span class="cx"> /// </summary>
</span><del>- public static ManagedSession OriginateHandleHangup(CoreSession aLegSession, string destination, TimeSpan timeout, Action<ManagedSession> onHangup) {
</del><ins>+ public static ManagedSession OriginateHandleHangup(CoreSession aLegSession, string destination, TimeSpan timeout, Action<ManagedSession> onHangup)
+ {
</ins><span class="cx"> var bleg = new ManagedSession();
</span><span class="cx">
</span><span class="cx"> bleg.originate_ondestroy_delegate = bleg.originate_ondestroy_method;
</span><del>- bleg.originate_onhangup_delegate = CreateStateHandlerDelegate(sess_b => {
- if (onHangup != null) {
</del><ins>+ bleg.originate_onhangup_delegate = CreateStateHandlerDelegate(sess_b =>
+ {
+ if (onHangup != null)
+ {
</ins><span class="cx"> onHangup(sess_b);
</span><span class="cx"> }
</span><span class="cx"> });
</span><span class="lines">@@ -196,35 +282,199 @@
</span><span class="cx"> bleg.originate_table.flags = (int)switch_state_handler_flag_t.SSH_FLAG_STICKY;
</span><span class="cx"> var res = 0 == bleg.originate(aLegSession, destination, (int)timeout.TotalSeconds, bleg.originate_table);
</span><span class="cx"> bleg.originate_keepalive_handle = GCHandle.Alloc(bleg, GCHandleType.Normal); // Prevent GC from eating the bleg
</span><del>- if (res) {
</del><ins>+ if (res)
+ {
</ins><span class="cx"> bleg.Initialize();
</span><span class="cx"> return bleg;
</span><del>- } else {
</del><ins>+ }
+ else
+ {
</ins><span class="cx"> // Dispose to free the lock
</span><span class="cx"> // The bleg lives on with its unmanaged memory freed
</span><span class="cx"> // Until CS_DESTROY gets called
</span><del>- bleg.Dispose();
</del><ins>+ bleg.Dispose();
</ins><span class="cx"> return null;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Convenience
</span><del>- public bool IsAvailable {
</del><ins>+ public bool IsAvailable
+ {
</ins><span class="cx"> get { return this.Ready(); }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- public Guid Uuid {
- get {
- if (allocated == 0) throw new InvalidOperationException("Session has not been initialized.");
</del><ins>+ public Guid Uuid
+ {
+ get
+ {
+ if (Allocated == 0) throw new InvalidOperationException("Session has not been initialized.");
</ins><span class="cx"> return new Guid(this.GetUuid());
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- 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);
</del><ins>+ 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);
</ins><span class="cx"> }
</span><ins>+ set
+ {
+ if (Allocated == 0) throw new InvalidOperationException("Session has not been initialized.");
+ base.CallCause = value;
+ }
</ins><span class="cx"> }
</span><ins>+
+ public void QueuePrivateEvent(IEvent sendME)
+ {
+ Event sendEE = sendME as Event;
+ if (sendEE == null) { return; }
+ base.QueuePrivateEvent(sendEE);
+ }
</ins><span class="cx"> }
</span><ins>+
+ 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 { }
</ins><span class="cx"> }
</span></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>
</body>
</html>