using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Diagnostics;
using System.Threading;
using System.Text;
namespace OpenMetaverse.Voice
{
public partial class VoiceGateway
{
public delegate void DaemonRunningCallback();
public delegate void DaemonExitedCallback();
public delegate void DaemonCouldntRunCallback();
public delegate void DaemonConnectedCallback();
public delegate void DaemonDisconnectedCallback();
public delegate void DaemonCouldntConnectCallback();
public event DaemonRunningCallback OnDaemonRunning;
public event DaemonExitedCallback OnDaemonExited;
public event DaemonCouldntRunCallback OnDaemonCouldntRun;
public event DaemonConnectedCallback OnDaemonConnected;
public event DaemonDisconnectedCallback OnDaemonDisconnected;
public event DaemonCouldntConnectCallback OnDaemonCouldntConnect;
public bool DaemonIsRunning { get { return daemonIsRunning; } }
public bool DaemonIsConnected { get { return daemonIsConnected; } }
public int RequestId { get { return requestId; } }
protected Process daemonProcess;
protected ManualResetEvent daemonLoopSignal = new ManualResetEvent(false);
protected TCPPipe daemonPipe;
protected bool daemonIsRunning = false;
protected bool daemonIsConnected = false;
protected int requestId = 0;
#region Daemon Management
///
/// Starts a thread that keeps the daemon running
///
///
///
public void StartDaemon(string path, string args)
{
StopDaemon();
daemonLoopSignal.Set();
Thread thread = new Thread(new ThreadStart(delegate()
{
while (daemonLoopSignal.WaitOne(500, false))
{
daemonProcess = new Process();
daemonProcess.StartInfo.FileName = path;
daemonProcess.StartInfo.Arguments = args;
daemonProcess.StartInfo.UseShellExecute = false;
bool ok = true;
if (!File.Exists(path))
ok = false;
if (ok)
{
// Attempt to start the process
if (!daemonProcess.Start())
ok = false;
}
if (!ok)
{
daemonIsRunning = false;
daemonLoopSignal.Reset();
if (OnDaemonCouldntRun != null)
{
try { OnDaemonCouldntRun(); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, null, e); }
}
return;
}
else
{
daemonIsRunning = true;
if (OnDaemonRunning != null)
{
try { OnDaemonRunning(); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, null, e); }
}
Logger.DebugLog("Started voice daemon, waiting for exit...");
daemonProcess.WaitForExit();
Logger.DebugLog("Voice daemon exited");
daemonIsRunning = false;
if (OnDaemonExited != null)
{
try { OnDaemonExited(); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, null, e); }
}
}
}
}));
thread.Start();
}
///
/// Stops the daemon and the thread keeping it running
///
public void StopDaemon()
{
daemonLoopSignal.Reset();
if (daemonProcess != null)
{
try
{
daemonProcess.Kill();
}
catch (InvalidOperationException ex)
{
Logger.Log("Failed to stop the voice daemon", Helpers.LogLevel.Error, ex);
}
}
}
///
///
///
///
///
///
public bool ConnectToDaemon(string address, int port)
{
daemonIsConnected = false;
daemonPipe = new TCPPipe();
daemonPipe.OnDisconnected +=
delegate(SocketException e)
{
if (OnDaemonDisconnected != null)
{
try { OnDaemonDisconnected(); }
catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, null, ex); }
}
};
daemonPipe.OnReceiveLine += new TCPPipe.OnReceiveLineCallback(daemonPipe_OnReceiveLine);
SocketException se = daemonPipe.Connect(address, port);
if (se == null)
{
daemonIsConnected = true;
if (OnDaemonConnected != null)
{
try { OnDaemonConnected(); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, null, e); }
}
return true;
}
else
{
daemonIsConnected = false;
if (OnDaemonCouldntConnect != null)
{
try { OnDaemonCouldntConnect(); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, null, e); }
}
Logger.Log("Voice daemon connection failed: " + se.Message, Helpers.LogLevel.Error);
return false;
}
}
#endregion Daemon Management
public int Request(string action)
{
return Request(action, null);
}
public int Request(string action, string requestXML)
{
int returnId = requestId;
if (daemonIsConnected)
{
StringBuilder sb = new StringBuilder();
sb.Append(String.Format("");
}
else
{
sb.Append(">");
sb.Append(requestXML);
sb.Append("");
}
sb.Append("\n\n\n");
daemonPipe.SendData(Encoding.ASCII.GetBytes(sb.ToString()));
return returnId;
}
else
{
return -1;
}
}
public static string MakeXML(string name, string text)
{
if (string.IsNullOrEmpty(text))
return string.Format("<{0} />", name);
else
return string.Format("<{0}>{1}{0}>", name, text);
}
private void daemonPipe_OnReceiveLine(string line)
{
if (line.Substring(0, 10) == " CaptureDevices = new List();
foreach (CaptureDevice device in rsp.Results.CaptureDevices)
CaptureDevices.Add(device.Device);
OnAuxGetCaptureDevicesResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, CaptureDevices, rsp.Results.CurrentCaptureDevice.Device, rsp.InputXml.Request);
}
break;
case "Aux.GetRenderDevices.1":
if (OnAuxGetRenderDevicesResponse != null)
{
List RenderDevices = new List();
foreach (RenderDevice device in rsp.Results.RenderDevices)
RenderDevices.Add(device.Device);
OnAuxGetRenderDevicesResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, RenderDevices, rsp.Results.CurrentRenderDevice.Device, rsp.InputXml.Request);
}
break;
case "Aux.SetRenderDevice.1":
if (OnAuxSetRenderDeviceResponse != null)
{
OnAuxSetRenderDeviceResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, rsp.InputXml.Request);
}
break;
case "Aux.SetCaptureDevice.1":
if (OnAuxSetCaptureDeviceResponse != null)
{
OnAuxSetCaptureDeviceResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, rsp.InputXml.Request);
}
break;
case "Session.RenderAudioStart.1":
if (OnSessionRenderAudioStartResponse != null)
{
OnSessionRenderAudioStartResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, rsp.InputXml.Request);
}
break;
case "Session.RenderAudioStop.1":
if (OnSessionRenderAudioStopResponse != null)
{
OnSessionRenderAudioStopResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, rsp.InputXml.Request);
}
break;
case "Aux.CaptureAudioStart.1":
if (OnAuxCaptureAudioStartResponse != null)
{
OnAuxCaptureAudioStartResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, rsp.InputXml.Request);
}
break;
case "Aux.CaptureAudioStop.1":
if (OnAuxCaptureAudioStopResponse != null)
{
OnAuxCaptureAudioStopResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, rsp.InputXml.Request);
}
break;
case "Aux.SetMicLevel.1":
if (OnAuxSetMicLevelResponse != null)
{
OnAuxSetMicLevelResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, rsp.InputXml.Request);
}
break;
case "Aux.SetSpeakerLevel.1":
if (OnAuxSetSpeakerLevelResponse != null)
{
OnAuxSetSpeakerLevelResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, rsp.InputXml.Request);
}
break;
case "Account.Login.1":
if (OnAccountLoginResponse != null)
{
OnAccountLoginResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, rsp.Results.AccountHandle, rsp.InputXml.Request);
}
break;
case "Account.Logout.1":
if (OnAccountLogoutResponse != null)
{
OnAccountLogoutResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, rsp.InputXml.Request);
}
break;
case "Session.Create.1":
if (OnSessionCreateResponse != null)
{
OnSessionCreateResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, rsp.Results.SessionHandle, rsp.InputXml.Request);
}
break;
case "Session.Connect.1":
if (OnSessionConnectResponse != null)
{
OnSessionConnectResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, rsp.InputXml.Request);
}
break;
case "Session.Terminate.1":
if (OnSessionTerminateResponse != null)
{
OnSessionTerminateResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, rsp.InputXml.Request);
}
break;
case "Session.SetParticipantVolumeForMe.1":
if (OnSessionSetParticipantVolumeForMeResponse != null)
{
OnSessionSetParticipantVolumeForMeResponse(int.Parse(rsp.ReturnCode), int.Parse(rsp.Results.StatusCode), rsp.Results.StatusString, rsp.InputXml.Request);
}
break;
default:
Logger.Log("Unimplemented response from the voice daemon: " + line, Helpers.LogLevel.Error);
break;
}
}
else if (line.Substring(0, 7) == "