Initial commit

I wish I could figure out how to have PlexVie be out of the LibOMV tree but its just not working die to a DLL not found exception about libopenjpeg. (Yes the dll is in the bin folder)
This will do for now
This commit is contained in:
Blake Bourque
2015-06-18 22:15:24 -04:00
commit 0bb2dff347
382 changed files with 273704 additions and 0 deletions
@@ -0,0 +1,80 @@
<?xml version="1.0" ?>
<project name="OpenMetaverse.Utilities" default="build">
<target name="build">
<echo message="Build Directory is ${build.dir}" />
<mkdir dir="${build.dir}" />
<csc target="library" debug="${build.debug}" unsafe="True" warnaserror="False" define="TRACE" nostdlib="False" main="" doc="${build.dir}/OpenMetaverse.Utilities.XML" output="${build.dir}/${project::get-name()}.dll">
<resources prefix="OpenMetaverse.Utilities" dynamicprefix="true" >
</resources>
<sources failonempty="true">
<include name="RegistrationApi.cs" />
<include name="Utilities.cs" />
<include name="VoiceManager.cs" />
<include name="VoiceManagerBlocking.cs" />
<include name="Properties/AssemblyInfo.cs" />
</sources>
<references basedir="${project::get-base-directory()}">
<lib>
<include name="${project::get-base-directory()}" />
<include name="${build.dir}" />
</lib>
<include name="System.dll" />
<include name="System.Xml.dll" />
<include name="System.Data.dll" />
<include name="${build.dir}/OpenMetaverse.dll" />
<include name="${build.dir}/OpenMetaverseTypes.dll" />
<include name="${build.dir}/OpenMetaverse.StructuredData.dll" />
</references>
<nowarn>
<warning number="1591" />
<warning number="1574" />
<warning number="0419" />
<warning number="0618" />
</nowarn>
</csc>
</target>
<target name="clean">
<delete dir="${bin.dir}" failonerror="false" />
<delete dir="${obj.dir}" failonerror="false" />
</target>
<target name="doc" description="Creates documentation.">
<property name="doc.target" value="" />
<if test="${platform::is-unix()}">
<property name="doc.target" value="Web" />
</if>
<ndoc failonerror="false" verbose="true">
<assemblies basedir="${project::get-base-directory()}">
<include name="${build.dir}/${project::get-name()}.dll" />
</assemblies>
<summaries basedir="${project::get-base-directory()}">
<include name="${build.dir}/${project::get-name()}.xml"/>
</summaries>
<referencepaths basedir="${project::get-base-directory()}">
<include name="${build.dir}" />
</referencepaths>
<documenters>
<documenter name="MSDN">
<property name="OutputDirectory" value="${build.dir}/doc/${project::get-name()}" />
<property name="OutputTarget" value="${doc.target}" />
<property name="HtmlHelpName" value="${project::get-name()}" />
<property name="IncludeFavorites" value="False" />
<property name="Title" value="${project::get-name()} SDK Documentation" />
<property name="SplitTOCs" value="False" />
<property name="DefaulTOC" value="" />
<property name="ShowVisualBasic" value="True" />
<property name="AutoDocumentConstructors" value="True" />
<property name="ShowMissingSummaries" value="${build.debug}" />
<property name="ShowMissingRemarks" value="${build.debug}" />
<property name="ShowMissingParams" value="${build.debug}" />
<property name="ShowMissingReturns" value="${build.debug}" />
<property name="ShowMissingValues" value="${build.debug}" />
<property name="DocumentInternals" value="False" />
<property name="DocumentPrivates" value="False" />
<property name="DocumentProtected" value="True" />
<property name="DocumentEmptyNamespaces" value="${build.debug}" />
<property name="IncludeAssemblyVersion" value="True" />
</documenter>
</documenters>
</ndoc>
</target>
</project>
@@ -0,0 +1,34 @@
<Project name="OpenMetaverse.Utilities" description="" standardNamespace="OpenMetaverse.Utilities" newfilesearch="None" enableviewstate="True" fileversion="2.0" language="C#" clr-version="Net_2_0" ctype="DotNetProject">
<Configurations active="Debug">
<Configuration name="Release" ctype="DotNetProjectConfiguration">
<Output directory="./../bin/" assembly="OpenMetaverse.Utilities" executeScript="" executeBeforeBuild="" executeAfterBuild="" executeBeforeBuildArguments="" executeAfterBuildArguments="" />
<Build debugmode="True" target="Library" />
<Execution runwithwarnings="True" consolepause="True" runtime="MsNet" clr-version="Net_2_0" />
<CodeGeneration compiler="Csc" warninglevel="4" nowarn="1591,1574,0419,0618" includedebuginformation="False" optimize="True" unsafecodeallowed="True" generateoverflowchecks="False" mainclass="" target="Library" definesymbols="TRACE" generatexmldocumentation="True" win32Icon="" ctype="CSharpCompilerParameters" />
</Configuration>
<Configuration name="Debug" ctype="DotNetProjectConfiguration">
<Output directory="./../bin/" assembly="OpenMetaverse.Utilities" executeScript="" executeBeforeBuild="" executeAfterBuild="" executeBeforeBuildArguments="" executeAfterBuildArguments="" />
<Build debugmode="True" target="Library" />
<Execution runwithwarnings="True" consolepause="True" runtime="MsNet" clr-version="Net_2_0" />
<CodeGeneration compiler="Csc" warninglevel="4" nowarn="1591,1574,0419,0618" includedebuginformation="True" optimize="False" unsafecodeallowed="True" generateoverflowchecks="False" mainclass="" target="Library" definesymbols="TRACE;DEBUG" generatexmldocumentation="False" win32Icon="" ctype="CSharpCompilerParameters" />
</Configuration>
</Configurations>
<DeploymentInformation target="" script="" strategy="File">
<excludeFiles />
</DeploymentInformation>
<Contents>
<File name="./RegistrationApi.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name="./Utilities.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name="./VoiceManager.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name="./VoiceManagerBlocking.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
<File name="./Properties/AssemblyInfo.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
</Contents>
<References>
<ProjectReference type="Gac" localcopy="False" refto="System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<ProjectReference type="Gac" localcopy="False" refto="System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<ProjectReference type="Gac" localcopy="False" refto="System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<ProjectReference type="Project" localcopy="False" refto="OpenMetaverse" />
<ProjectReference type="Project" localcopy="False" refto="OpenMetaverseTypes" />
<ProjectReference type="Project" localcopy="False" refto="OpenMetaverse.StructuredData" />
</References>
</Project>
@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("OpenMetaverse.Utilities")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OpenMetaverse.Utilities")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("b77aa07a-daa3-431f-b5aa-0c9c5e2151fd")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+355
View File
@@ -0,0 +1,355 @@
/*
* Copyright (c) 2006-2014, openmetaverse.org
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the openmetaverse.org nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Threading;
using System.Text;
using OpenMetaverse.StructuredData;
using OpenMetaverse.Http;
namespace OpenMetaverse
{
public class RegistrationApi
{
const int REQUEST_TIMEOUT = 1000 * 100;
private struct UserInfo
{
public string FirstName;
public string LastName;
public string Password;
}
private struct RegistrationCaps
{
public Uri CreateUser;
public Uri CheckName;
public Uri GetLastNames;
public Uri GetErrorCodes;
}
public struct LastName
{
public int ID;
public string Name;
}
/// <summary>
/// See https://secure-web6.secondlife.com/developers/third_party_reg/#service_create_user or
/// https://wiki.secondlife.com/wiki/RegAPIDoc for description
/// </summary>
public class CreateUserParam
{
public string FirstName;
public LastName LastName;
public string Email;
public string Password;
public DateTime Birthdate;
// optional:
public Nullable<int> LimitedToEstate;
public string StartRegionName;
public Nullable<Vector3> StartLocation;
public Nullable<Vector3> StartLookAt;
}
private UserInfo _userInfo;
private RegistrationCaps _caps;
private int _initializing;
private List<LastName> _lastNames = new List<LastName>();
private Dictionary<int, string> _errors = new Dictionary<int, string>();
public bool Initializing
{
get
{
System.Diagnostics.Debug.Assert(_initializing <= 0);
return (_initializing < 0);
}
}
public List<LastName> LastNames
{
get
{
lock (_lastNames)
{
if (_lastNames.Count <= 0)
GatherLastNames();
}
return _lastNames;
}
}
public RegistrationApi(string firstName, string lastName, string password)
{
_initializing = -2;
_userInfo = new UserInfo();
_userInfo.FirstName = firstName;
_userInfo.LastName = lastName;
_userInfo.Password = password;
GatherCaps();
}
public void WaitForInitialization()
{
while (Initializing)
System.Threading.Thread.Sleep(10);
}
public Uri RegistrationApiCaps
{
get { return new Uri("https://cap.secondlife.com/get_reg_capabilities"); }
}
private void GatherCaps()
{
// build post data
byte[] postData = Encoding.ASCII.GetBytes(
String.Format("first_name={0}&last_name={1}&password={2}", _userInfo.FirstName, _userInfo.LastName,
_userInfo.Password));
CapsClient request = new CapsClient(RegistrationApiCaps);
request.OnComplete += new CapsClient.CompleteCallback(GatherCapsResponse);
request.BeginGetResponse(postData, "application/x-www-form-urlencoded", REQUEST_TIMEOUT);
}
private void GatherCapsResponse(CapsClient client, OSD response, Exception error)
{
if (response is OSDMap)
{
OSDMap respTable = (OSDMap)response;
// parse
_caps = new RegistrationCaps();
_caps.CreateUser = respTable["create_user"].AsUri();
_caps.CheckName = respTable["check_name"].AsUri();
_caps.GetLastNames = respTable["get_last_names"].AsUri();
_caps.GetErrorCodes = respTable["get_error_codes"].AsUri();
// finalize
_initializing++;
GatherErrorMessages();
}
}
private void GatherErrorMessages()
{
if (_caps.GetErrorCodes == null)
throw new InvalidOperationException("access denied"); // this should work even for not-approved users
CapsClient request = new CapsClient(_caps.GetErrorCodes);
request.OnComplete += new CapsClient.CompleteCallback(GatherErrorMessagesResponse);
request.BeginGetResponse(REQUEST_TIMEOUT);
}
private void GatherErrorMessagesResponse(CapsClient client, OSD response, Exception error)
{
if (response is OSDMap)
{
// parse
//FIXME: wtf?
//foreach (KeyValuePair<string, object> error in (Dictionary<string, object>)response)
//{
//StringBuilder sb = new StringBuilder();
//sb.Append(error[1]);
//sb.Append(" (");
//sb.Append(error[0]);
//sb.Append("): ");
//sb.Append(error[2]);
//_errors.Add((int)error[0], sb.ToString());
//}
// finalize
_initializing++;
}
}
public void GatherLastNames()
{
if (Initializing)
throw new InvalidOperationException("still initializing");
if (_caps.GetLastNames == null)
throw new InvalidOperationException("access denied: only approved developers have access to the registration api");
CapsClient request = new CapsClient(_caps.GetLastNames);
request.OnComplete += new CapsClient.CompleteCallback(GatherLastNamesResponse);
request.BeginGetResponse(REQUEST_TIMEOUT);
// FIXME: Block
}
private void GatherLastNamesResponse(CapsClient client, OSD response, Exception error)
{
if (response is OSDMap)
{
//LLSDMap respTable = (LLSDMap)response;
//FIXME:
//_lastNames = new List<LastName>(respTable.Count);
//for (Dictionary<string, object>.Enumerator it = respTable.GetEnumerator(); it.MoveNext(); )
//{
// LastName ln = new LastName();
// ln.ID = int.Parse(it.Current.Key.ToString());
// ln.Name = it.Current.Value.ToString();
// _lastNames.Add(ln);
//}
//_lastNames.Sort(new Comparison<LastName>(delegate(LastName a, LastName b) { return a.Name.CompareTo(b.Name); }));
}
}
public bool CheckName(string firstName, LastName lastName)
{
if (Initializing)
throw new InvalidOperationException("still initializing");
if (_caps.CheckName == null)
throw new InvalidOperationException("access denied; only approved developers have access to the registration api");
// Create the POST data
OSDMap query = new OSDMap();
query.Add("username", OSD.FromString(firstName));
query.Add("last_name_id", OSD.FromInteger(lastName.ID));
//byte[] postData = OSDParser.SerializeXmlBytes(query);
CapsClient request = new CapsClient(_caps.CheckName);
request.OnComplete += new CapsClient.CompleteCallback(CheckNameResponse);
request.BeginGetResponse(REQUEST_TIMEOUT);
// FIXME:
return false;
}
private void CheckNameResponse(CapsClient client, OSD response, Exception error)
{
if (response.Type == OSDType.Boolean)
{
// FIXME:
//(bool)response;
}
else
{
// FIXME:
}
}
/// <summary>
/// Returns the new user ID or throws an exception containing the error code
/// The error codes can be found here: https://wiki.secondlife.com/wiki/RegAPIError
/// </summary>
/// <param name="user">New user account to create</param>
/// <returns>The UUID of the new user account</returns>
public UUID CreateUser(CreateUserParam user)
{
if (Initializing)
throw new InvalidOperationException("still initializing");
if (_caps.CreateUser == null)
throw new InvalidOperationException("access denied; only approved developers have access to the registration api");
// Create the POST data
OSDMap query = new OSDMap();
query.Add("username", OSD.FromString(user.FirstName));
query.Add("last_name_id", OSD.FromInteger(user.LastName.ID));
query.Add("email", OSD.FromString(user.Email));
query.Add("password", OSD.FromString(user.Password));
query.Add("dob", OSD.FromString(user.Birthdate.ToString("yyyy-MM-dd")));
if (user.LimitedToEstate != null)
query.Add("limited_to_estate", OSD.FromInteger(user.LimitedToEstate.Value));
if (!string.IsNullOrEmpty(user.StartRegionName))
query.Add("start_region_name", OSD.FromInteger(user.LimitedToEstate.Value));
if (user.StartLocation != null)
{
query.Add("start_local_x", OSD.FromReal(user.StartLocation.Value.X));
query.Add("start_local_y", OSD.FromReal(user.StartLocation.Value.Y));
query.Add("start_local_z", OSD.FromReal(user.StartLocation.Value.Z));
}
if (user.StartLookAt != null)
{
query.Add("start_look_at_x", OSD.FromReal(user.StartLookAt.Value.X));
query.Add("start_look_at_y", OSD.FromReal(user.StartLookAt.Value.Y));
query.Add("start_look_at_z", OSD.FromReal(user.StartLookAt.Value.Z));
}
//byte[] postData = OSDParser.SerializeXmlBytes(query);
// Make the request
CapsClient request = new CapsClient(_caps.CreateUser);
request.OnComplete += new CapsClient.CompleteCallback(CreateUserResponse);
request.BeginGetResponse(REQUEST_TIMEOUT);
// FIXME: Block
return UUID.Zero;
}
private void CreateUserResponse(CapsClient client, OSD response, Exception error)
{
if (response is OSDMap)
{
// everything is okay
// FIXME:
//return new UUID(((Dictionary<string, object>)response)["agent_id"].ToString());
}
else
{
// an error happened
OSDArray al = (OSDArray)response;
StringBuilder sb = new StringBuilder();
foreach (OSD ec in al)
{
if (sb.Length > 0)
sb.Append("; ");
sb.Append(_errors[ec.AsInteger()]);
}
// FIXME:
//throw new Exception("failed to create user: " + sb.ToString());
}
}
}
}
+269
View File
@@ -0,0 +1,269 @@
/*
* Copyright (c) 2006-2014, openmetaverse.org
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the openmetaverse.org nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using OpenMetaverse;
using OpenMetaverse.Packets;
namespace OpenMetaverse.Utilities
{
/// <summary>
///
/// </summary>
public enum WaterType
{
/// <summary></summary>
Unknown,
/// <summary></summary>
Dry,
/// <summary></summary>
Waterfront,
/// <summary></summary>
Underwater
}
public static class Realism
{
/// <summary>
/// Aims at the specified position, enters mouselook, presses and
/// releases the left mouse button, and leaves mouselook
/// </summary>
/// <param name="client"></param>
/// <param name="target">Target to shoot at</param>
/// <returns></returns>
public static bool Shoot(GridClient client, Vector3 target)
{
if (client.Self.Movement.TurnToward(target))
return Shoot(client);
else
return false;
}
/// <summary>
/// Enters mouselook, presses and releases the left mouse button, and leaves mouselook
/// </summary>
/// <returns></returns>
public static bool Shoot(GridClient client)
{
if (client.Settings.SEND_AGENT_UPDATES)
{
client.Self.Movement.Mouselook = true;
client.Self.Movement.MLButtonDown = true;
client.Self.Movement.SendUpdate();
client.Self.Movement.MLButtonUp = true;
client.Self.Movement.MLButtonDown = false;
client.Self.Movement.FinishAnim = true;
client.Self.Movement.SendUpdate();
client.Self.Movement.Mouselook = false;
client.Self.Movement.MLButtonUp = false;
client.Self.Movement.FinishAnim = false;
client.Self.Movement.SendUpdate();
return true;
}
else
{
Logger.Log("Attempted Shoot but agent updates are disabled", Helpers.LogLevel.Warning, client);
return false;
}
}
/// <summary>
/// A psuedo-realistic chat function that uses the typing sound and
/// animation, types at three characters per second, and randomly
/// pauses. This function will block until the message has been sent
/// </summary>
/// <param name="client">A reference to the client that will chat</param>
/// <param name="message">The chat message to send</param>
public static void Chat(GridClient client, string message)
{
Chat(client, message, ChatType.Normal, 3);
}
/// <summary>
/// A psuedo-realistic chat function that uses the typing sound and
/// animation, types at a given rate, and randomly pauses. This
/// function will block until the message has been sent
/// </summary>
/// <param name="client">A reference to the client that will chat</param>
/// <param name="message">The chat message to send</param>
/// <param name="type">The chat type (usually Normal, Whisper or Shout)</param>
/// <param name="cps">Characters per second rate for chatting</param>
public static void Chat(GridClient client, string message, ChatType type, int cps)
{
Random rand = new Random();
int characters = 0;
bool typing = true;
// Start typing
client.Self.Chat(String.Empty, 0, ChatType.StartTyping);
client.Self.AnimationStart(Animations.TYPE, false);
while (characters < message.Length)
{
if (!typing)
{
// Start typing again
client.Self.Chat(String.Empty, 0, ChatType.StartTyping);
client.Self.AnimationStart(Animations.TYPE, false);
typing = true;
}
else
{
// Randomly pause typing
if (rand.Next(10) >= 9)
{
client.Self.Chat(String.Empty, 0, ChatType.StopTyping);
client.Self.AnimationStop(Animations.TYPE, false);
typing = false;
}
}
// Sleep for a second and increase the amount of characters we've typed
System.Threading.Thread.Sleep(1000);
characters += cps;
}
// Send the message
client.Self.Chat(message, 0, type);
// Stop typing
client.Self.Chat(String.Empty, 0, ChatType.StopTyping);
client.Self.AnimationStop(Animations.TYPE, false);
}
}
public class ConnectionManager
{
private GridClient Client;
private ulong SimHandle;
private Vector3 Position = Vector3.Zero;
private System.Timers.Timer CheckTimer;
public ConnectionManager(GridClient client, int timerFrequency)
{
Client = client;
CheckTimer = new System.Timers.Timer(timerFrequency);
CheckTimer.Elapsed += new System.Timers.ElapsedEventHandler(CheckTimer_Elapsed);
}
public static bool PersistentLogin(GridClient client, string firstName, string lastName, string password,
string userAgent, string start, string author)
{
int unknownLogins = 0;
Start:
if (client.Network.Login(firstName, lastName, password, userAgent, start, author))
{
Logger.Log("Logged in to " + client.Network.CurrentSim, Helpers.LogLevel.Info, client);
return true;
}
else
{
if (client.Network.LoginErrorKey == "god")
{
Logger.Log("Grid is down, waiting 10 minutes", Helpers.LogLevel.Warning, client);
LoginWait(10);
goto Start;
}
else if (client.Network.LoginErrorKey == "key")
{
Logger.Log("Bad username or password, giving up on login", Helpers.LogLevel.Error, client);
return false;
}
else if (client.Network.LoginErrorKey == "presence")
{
Logger.Log("Server is still logging us out, waiting 1 minute", Helpers.LogLevel.Warning, client);
LoginWait(1);
goto Start;
}
else if (client.Network.LoginErrorKey == "disabled")
{
Logger.Log("This account has been banned! Giving up on login", Helpers.LogLevel.Error, client);
return false;
}
else if (client.Network.LoginErrorKey == "timed out" ||client.Network.LoginErrorKey == "no connection" )
{
Logger.Log("Login request timed out, waiting 1 minute", Helpers.LogLevel.Warning, client);
LoginWait(1);
goto Start;
} else if (client.Network.LoginErrorKey == "bad response") {
Logger.Log("Login server returned unparsable result", Helpers.LogLevel.Warning, client);
LoginWait(1);
goto Start;
} else
{
++unknownLogins;
if (unknownLogins < 5)
{
Logger.Log("Unknown login error, waiting 2 minutes: " + client.Network.LoginErrorKey,
Helpers.LogLevel.Warning, client);
LoginWait(2);
goto Start;
}
else
{
Logger.Log("Too many unknown login error codes, giving up", Helpers.LogLevel.Error, client);
return false;
}
}
}
}
public void StayInSim(ulong handle, Vector3 desiredPosition)
{
SimHandle = handle;
Position = desiredPosition;
CheckTimer.Start();
}
private static void LoginWait(int minutes)
{
Thread.Sleep(1000 * 60 * minutes);
}
private void CheckTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (SimHandle != 0)
{
if (Client.Network.CurrentSim.Handle != 0 &&
Client.Network.CurrentSim.Handle != SimHandle)
{
// Attempt to move to our target sim
Client.Self.Teleport(SimHandle, Position);
}
}
}
}
}
+827
View File
@@ -0,0 +1,827 @@
/*
* Copyright (c) 2006-2014, openmetaverse.org
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the openmetaverse.org nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.IO;
using System.Xml;
using System.Threading;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenMetaverse.Http;
using OpenMetaverse.Interfaces;
using OpenMetaverse.Messages.Linden;
namespace OpenMetaverse.Utilities
{
public enum VoiceStatus
{
StatusLoginRetry,
StatusLoggedIn,
StatusJoining,
StatusJoined,
StatusLeftChannel,
BeginErrorStatus,
ErrorChannelFull,
ErrorChannelLocked,
ErrorNotAvailable,
ErrorUnknown
}
public enum VoiceServiceType
{
/// <summary>Unknown voice service level</summary>
Unknown,
/// <summary>Spatialized local chat</summary>
TypeA,
/// <summary>Remote multi-party chat</summary>
TypeB,
/// <summary>One-to-one and small group chat</summary>
TypeC
}
public partial class VoiceManager
{
public const int VOICE_MAJOR_VERSION = 1;
public const string DAEMON_ARGS = " -p tcp -h -c -ll ";
public const int DAEMON_LOG_LEVEL = 1;
public const int DAEMON_PORT = 44124;
public const string VOICE_RELEASE_SERVER = "bhr.vivox.com";
public const string VOICE_DEBUG_SERVER = "bhd.vivox.com";
public const string REQUEST_TERMINATOR = "\n\n\n";
public delegate void LoginStateChangeCallback(int cookie, string accountHandle, int statusCode, string statusString, int state);
public delegate void NewSessionCallback(int cookie, string accountHandle, string eventSessionHandle, int state, string nameString, string uriString);
public delegate void SessionStateChangeCallback(int cookie, string uriString, int statusCode, string statusString, string eventSessionHandle, int state, bool isChannel, string nameString);
public delegate void ParticipantStateChangeCallback(int cookie, string uriString, int statusCode, string statusString, int state, string nameString, string displayNameString, int participantType);
public delegate void ParticipantPropertiesCallback(int cookie, string uriString, int statusCode, string statusString, bool isLocallyMuted, bool isModeratorMuted, bool isSpeaking, int volume, float energy);
public delegate void AuxAudioPropertiesCallback(int cookie, float energy);
public delegate void BasicActionCallback(int cookie, int statusCode, string statusString);
public delegate void ConnectorCreatedCallback(int cookie, int statusCode, string statusString, string connectorHandle);
public delegate void LoginCallback(int cookie, int statusCode, string statusString, string accountHandle);
public delegate void SessionCreatedCallback(int cookie, int statusCode, string statusString, string sessionHandle);
public delegate void DevicesCallback(int cookie, int statusCode, string statusString, string currentDevice);
public delegate void ProvisionAccountCallback(string username, string password);
public delegate void ParcelVoiceInfoCallback(string regionName, int localID, string channelURI);
public event LoginStateChangeCallback OnLoginStateChange;
public event NewSessionCallback OnNewSession;
public event SessionStateChangeCallback OnSessionStateChange;
public event ParticipantStateChangeCallback OnParticipantStateChange;
public event ParticipantPropertiesCallback OnParticipantProperties;
public event AuxAudioPropertiesCallback OnAuxAudioProperties;
public event ConnectorCreatedCallback OnConnectorCreated;
public event LoginCallback OnLogin;
public event SessionCreatedCallback OnSessionCreated;
public event BasicActionCallback OnSessionConnected;
public event BasicActionCallback OnAccountLogout;
public event BasicActionCallback OnConnectorInitiateShutdown;
public event BasicActionCallback OnAccountChannelGetList;
public event BasicActionCallback OnSessionTerminated;
public event DevicesCallback OnCaptureDevices;
public event DevicesCallback OnRenderDevices;
public event ProvisionAccountCallback OnProvisionAccount;
public event ParcelVoiceInfoCallback OnParcelVoiceInfo;
public GridClient Client;
public string VoiceServer = VOICE_RELEASE_SERVER;
public bool Enabled;
protected Voice.TCPPipe _DaemonPipe;
protected VoiceStatus _Status;
protected int _CommandCookie = 0;
protected string _TuningSoundFile = String.Empty;
protected Dictionary<string, string> _ChannelMap = new Dictionary<string, string>();
protected List<string> _CaptureDevices = new List<string>();
protected List<string> _RenderDevices = new List<string>();
#region Response Processing Variables
private bool isEvent = false;
private bool isChannel = false;
private bool isLocallyMuted = false;
private bool isModeratorMuted = false;
private bool isSpeaking = false;
private int cookie = 0;
//private int returnCode = 0;
private int statusCode = 0;
private int volume = 0;
private int state = 0;
private int participantType = 0;
private float energy = 0f;
private string statusString = String.Empty;
//private string uuidString = String.Empty;
private string actionString = String.Empty;
private string connectorHandle = String.Empty;
private string accountHandle = String.Empty;
private string sessionHandle = String.Empty;
private string eventSessionHandle = String.Empty;
private string eventTypeString = String.Empty;
private string uriString = String.Empty;
private string nameString = String.Empty;
//private string audioMediaString = String.Empty;
private string displayNameString = String.Empty;
#endregion Response Processing Variables
public VoiceManager(GridClient client)
{
Client = client;
Client.Network.RegisterEventCallback("RequiredVoiceVersion", new Caps.EventQueueCallback(RequiredVoiceVersionEventHandler));
// Register callback handlers for the blocking functions
RegisterCallbacks();
Enabled = true;
}
public bool IsDaemonRunning()
{
throw new NotImplementedException();
}
public bool StartDaemon()
{
throw new NotImplementedException();
}
public void StopDaemon()
{
throw new NotImplementedException();
}
public bool ConnectToDaemon()
{
if (!Enabled) return false;
return ConnectToDaemon("127.0.0.1", DAEMON_PORT);
}
public bool ConnectToDaemon(string address, int port)
{
if (!Enabled) return false;
_DaemonPipe = new Voice.TCPPipe();
_DaemonPipe.OnDisconnected += new Voice.TCPPipe.OnDisconnectedCallback(_DaemonPipe_OnDisconnected);
_DaemonPipe.OnReceiveLine += new Voice.TCPPipe.OnReceiveLineCallback(_DaemonPipe_OnReceiveLine);
SocketException se = _DaemonPipe.Connect(address, port);
if (se == null)
{
return true;
}
else
{
Console.WriteLine("Connection failed: " + se.Message);
return false;
}
}
public Dictionary<string, string> GetChannelMap()
{
return new Dictionary<string, string>(_ChannelMap);
}
public List<string> CurrentCaptureDevices()
{
return new List<string>(_CaptureDevices);
}
public List<string> CurrentRenderDevices()
{
return new List<string>(_RenderDevices);
}
public string VoiceAccountFromUUID(UUID id)
{
string result = "x" + Convert.ToBase64String(id.GetBytes());
return result.Replace('+', '-').Replace('/', '_');
}
public UUID UUIDFromVoiceAccount(string accountName)
{
if (accountName.Length == 25 && accountName[0] == 'x' && accountName[23] == '=' && accountName[24] == '=')
{
accountName = accountName.Replace('/', '_').Replace('+', '-');
byte[] idBytes = Convert.FromBase64String(accountName);
if (idBytes.Length == 16)
return new UUID(idBytes, 0);
else
return UUID.Zero;
}
else
{
return UUID.Zero;
}
}
public string SIPURIFromVoiceAccount(string account)
{
return String.Format("sip:{0}@{1}", account, VoiceServer);
}
public int RequestCaptureDevices()
{
if (_DaemonPipe.Connected)
{
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(String.Format(
"<Request requestId=\"{0}\" action=\"Aux.GetCaptureDevices.1\"></Request>{1}",
_CommandCookie++,
REQUEST_TERMINATOR)));
return _CommandCookie - 1;
}
else
{
Logger.Log("VoiceManager.RequestCaptureDevices() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
return -1;
}
}
public int RequestRenderDevices()
{
if (_DaemonPipe.Connected)
{
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(String.Format(
"<Request requestId=\"{0}\" action=\"Aux.GetRenderDevices.1\"></Request>{1}",
_CommandCookie++,
REQUEST_TERMINATOR)));
return _CommandCookie - 1;
}
else
{
Logger.Log("VoiceManager.RequestRenderDevices() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
return -1;
}
}
public int RequestCreateConnector()
{
return RequestCreateConnector(VoiceServer);
}
public int RequestCreateConnector(string voiceServer)
{
if (_DaemonPipe.Connected)
{
VoiceServer = voiceServer;
string accountServer = String.Format("https://www.{0}/api2/", VoiceServer);
string logPath = ".";
StringBuilder request = new StringBuilder();
request.Append(String.Format("<Request requestId=\"{0}\" action=\"Connector.Create.1\">", _CommandCookie++));
request.Append("<ClientName>V2 SDK</ClientName>");
request.Append(String.Format("<AccountManagementServer>{0}</AccountManagementServer>", accountServer));
request.Append("<Logging>");
request.Append("<Enabled>false</Enabled>");
request.Append(String.Format("<Folder>{0}</Folder>", logPath));
request.Append("<FileNamePrefix>vivox-gateway</FileNamePrefix>");
request.Append("<FileNameSuffix>.log</FileNameSuffix>");
request.Append("<LogLevel>0</LogLevel>");
request.Append("</Logging>");
request.Append("</Request>");
request.Append(REQUEST_TERMINATOR);
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(request.ToString()));
return _CommandCookie - 1;
}
else
{
Logger.Log("VoiceManager.CreateConnector() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
return -1;
}
}
private bool RequestVoiceInternal(string me, CapsClient.CompleteCallback callback, string capsName)
{
if (Enabled && Client.Network.Connected)
{
if (Client.Network.CurrentSim != null && Client.Network.CurrentSim.Caps != null)
{
Uri url = Client.Network.CurrentSim.Caps.CapabilityURI(capsName);
if (url != null)
{
CapsClient request = new CapsClient(url);
OSDMap body = new OSDMap();
request.OnComplete += new CapsClient.CompleteCallback(callback);
request.BeginGetResponse(body, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
return true;
}
else
{
Logger.Log("VoiceManager." + me + "(): " + capsName + " capability is missing",
Helpers.LogLevel.Info, Client);
return false;
}
}
}
Logger.Log("VoiceManager.RequestVoiceInternal(): Voice system is currently disabled",
Helpers.LogLevel.Info, Client);
return false;
}
public bool RequestProvisionAccount()
{
return RequestVoiceInternal("RequestProvisionAccount", ProvisionCapsResponse, "ProvisionVoiceAccountRequest");
}
public bool RequestParcelVoiceInfo()
{
return RequestVoiceInternal("RequestParcelVoiceInfo", ParcelVoiceInfoResponse, "ParcelVoiceInfoRequest");
}
public int RequestLogin(string accountName, string password, string connectorHandle)
{
if (_DaemonPipe.Connected)
{
StringBuilder request = new StringBuilder();
request.Append(String.Format("<Request requestId=\"{0}\" action=\"Account.Login.1\">", _CommandCookie++));
request.Append(String.Format("<ConnectorHandle>{0}</ConnectorHandle>", connectorHandle));
request.Append(String.Format("<AccountName>{0}</AccountName>", accountName));
request.Append(String.Format("<AccountPassword>{0}</AccountPassword>", password));
request.Append("<AudioSessionAnswerMode>VerifyAnswer</AudioSessionAnswerMode>");
request.Append("<AccountURI />");
request.Append("<ParticipantPropertyFrequency>10</ParticipantPropertyFrequency>");
request.Append("<EnableBuddiesAndPresence>false</EnableBuddiesAndPresence>");
request.Append("</Request>");
request.Append(REQUEST_TERMINATOR);
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(request.ToString()));
return _CommandCookie - 1;
}
else
{
Logger.Log("VoiceManager.Login() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
return -1;
}
}
public int RequestSetRenderDevice(string deviceName)
{
if (_DaemonPipe.Connected)
{
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(String.Format(
"<Request requestId=\"{0}\" action=\"Aux.SetRenderDevice.1\"><RenderDeviceSpecifier>{1}</RenderDeviceSpecifier></Request>{2}",
_CommandCookie, deviceName, REQUEST_TERMINATOR)));
return _CommandCookie - 1;
}
else
{
Logger.Log("VoiceManager.RequestSetRenderDevice() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
return -1;
}
}
public int RequestStartTuningMode(int duration)
{
if (_DaemonPipe.Connected)
{
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(String.Format(
"<Request requestId=\"{0}\" action=\"Aux.CaptureAudioStart.1\"><Duration>{1}</Duration></Request>{2}",
_CommandCookie, duration, REQUEST_TERMINATOR)));
return _CommandCookie - 1;
}
else
{
Logger.Log("VoiceManager.RequestStartTuningMode() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
return -1;
}
}
public int RequestStopTuningMode()
{
if (_DaemonPipe.Connected)
{
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(String.Format(
"<Request requestId=\"{0}\" action=\"Aux.CaptureAudioStop.1\"></Request>{1}",
_CommandCookie, REQUEST_TERMINATOR)));
return _CommandCookie - 1;
}
else
{
Logger.Log("VoiceManager.RequestStopTuningMode() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
return _CommandCookie - 1;
}
}
public int RequestSetSpeakerVolume(int volume)
{
if (volume < 0 || volume > 100)
throw new ArgumentException("volume must be between 0 and 100", "volume");
if (_DaemonPipe.Connected)
{
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(String.Format(
"<Request requestId=\"{0}\" action=\"Aux.SetSpeakerLevel.1\"><Level>{1}</Level></Request>{2}",
_CommandCookie, volume, REQUEST_TERMINATOR)));
return _CommandCookie - 1;
}
else
{
Logger.Log("VoiceManager.RequestSetSpeakerVolume() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
return -1;
}
}
public int RequestSetCaptureVolume(int volume)
{
if (volume < 0 || volume > 100)
throw new ArgumentException("volume must be between 0 and 100", "volume");
if (_DaemonPipe.Connected)
{
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(String.Format(
"<Request requestId=\"{0}\" action=\"Aux.SetMicLevel.1\"><Level>{1}</Level></Request>{2}",
_CommandCookie, volume, REQUEST_TERMINATOR)));
return _CommandCookie - 1;
}
else
{
Logger.Log("VoiceManager.RequestSetCaptureVolume() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
return -1;
}
}
/// <summary>
/// Does not appear to be working
/// </summary>
/// <param name="fileName"></param>
/// <param name="loop"></param>
public int RequestRenderAudioStart(string fileName, bool loop)
{
if (_DaemonPipe.Connected)
{
_TuningSoundFile = fileName;
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(String.Format(
"<Request requestId=\"{0}\" action=\"Aux.RenderAudioStart.1\"><SoundFilePath>{1}</SoundFilePath><Loop>{2}</Loop></Request>{3}",
_CommandCookie++, _TuningSoundFile, (loop ? "1" : "0"), REQUEST_TERMINATOR)));
return _CommandCookie - 1;
}
else
{
Logger.Log("VoiceManager.RequestRenderAudioStart() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
return -1;
}
}
public int RequestRenderAudioStop()
{
if (_DaemonPipe.Connected)
{
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(String.Format(
"<Request requestId=\"{0}\" action=\"Aux.RenderAudioStop.1\"><SoundFilePath>{1}</SoundFilePath></Request>{2}",
_CommandCookie++, _TuningSoundFile, REQUEST_TERMINATOR)));
return _CommandCookie - 1;
}
else
{
Logger.Log("VoiceManager.RequestRenderAudioStop() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
return -1;
}
}
#region Callbacks
private void RequiredVoiceVersionEventHandler(string capsKey, IMessage message, Simulator simulator)
{
RequiredVoiceVersionMessage msg = (RequiredVoiceVersionMessage)message;
if (VOICE_MAJOR_VERSION != msg.MajorVersion)
{
Logger.Log(String.Format("Voice version mismatch! Got {0}, expecting {1}. Disabling the voice manager",
msg.MajorVersion, VOICE_MAJOR_VERSION), Helpers.LogLevel.Error, Client);
Enabled = false;
}
else
{
Logger.DebugLog("Voice version " + msg.MajorVersion + " verified", Client);
}
}
private void ProvisionCapsResponse(CapsClient client, OSD response, Exception error)
{
if (response is OSDMap)
{
OSDMap respTable = (OSDMap)response;
if (OnProvisionAccount != null)
{
try { OnProvisionAccount(respTable["username"].AsString(), respTable["password"].AsString()); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
}
}
}
private void ParcelVoiceInfoResponse(CapsClient client, OSD response, Exception error)
{
if (response is OSDMap)
{
OSDMap respTable = (OSDMap)response;
string regionName = respTable["region_name"].AsString();
int localID = (int)respTable["parcel_local_id"].AsInteger();
string channelURI = null;
if (respTable["voice_credentials"] is OSDMap)
{
OSDMap creds = (OSDMap)respTable["voice_credentials"];
channelURI = creds["channel_uri"].AsString();
}
if (OnParcelVoiceInfo != null) OnParcelVoiceInfo(regionName, localID, channelURI);
}
}
private void _DaemonPipe_OnDisconnected(SocketException se)
{
if (se != null) Console.WriteLine("Disconnected! " + se.Message);
else Console.WriteLine("Disconnected!");
}
private void _DaemonPipe_OnReceiveLine(string line)
{
XmlTextReader reader = new XmlTextReader(new StringReader(line));
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
{
if (reader.Depth == 0)
{
isEvent = (reader.Name == "Event");
if (isEvent || reader.Name == "Response")
{
for (int i = 0; i < reader.AttributeCount; i++)
{
reader.MoveToAttribute(i);
switch (reader.Name)
{
// case "requestId":
// uuidString = reader.Value;
// break;
case "action":
actionString = reader.Value;
break;
case "type":
eventTypeString = reader.Value;
break;
}
}
}
}
else
{
switch (reader.Name)
{
case "InputXml":
cookie = -1;
// Parse through here to get the cookie value
reader.Read();
if (reader.Name == "Request")
{
for (int i = 0; i < reader.AttributeCount; i++)
{
reader.MoveToAttribute(i);
if (reader.Name == "requestId")
{
Int32.TryParse(reader.Value, out cookie);
break;
}
}
}
if (cookie == -1)
{
Logger.Log("VoiceManager._DaemonPipe_OnReceiveLine(): Failed to parse InputXml for the cookie",
Helpers.LogLevel.Warning, Client);
}
break;
case "CaptureDevices":
_CaptureDevices.Clear();
break;
case "RenderDevices":
_RenderDevices.Clear();
break;
// case "ReturnCode":
// returnCode = reader.ReadElementContentAsInt();
// break;
case "StatusCode":
statusCode = reader.ReadElementContentAsInt();
break;
case "StatusString":
statusString = reader.ReadElementContentAsString();
break;
case "State":
state = reader.ReadElementContentAsInt();
break;
case "ConnectorHandle":
connectorHandle = reader.ReadElementContentAsString();
break;
case "AccountHandle":
accountHandle = reader.ReadElementContentAsString();
break;
case "SessionHandle":
sessionHandle = reader.ReadElementContentAsString();
break;
case "URI":
uriString = reader.ReadElementContentAsString();
break;
case "IsChannel":
isChannel = reader.ReadElementContentAsBoolean();
break;
case "Name":
nameString = reader.ReadElementContentAsString();
break;
// case "AudioMedia":
// audioMediaString = reader.ReadElementContentAsString();
// break;
case "ChannelName":
nameString = reader.ReadElementContentAsString();
break;
case "ParticipantURI":
uriString = reader.ReadElementContentAsString();
break;
case "DisplayName":
displayNameString = reader.ReadElementContentAsString();
break;
case "AccountName":
nameString = reader.ReadElementContentAsString();
break;
case "ParticipantType":
participantType = reader.ReadElementContentAsInt();
break;
case "IsLocallyMuted":
isLocallyMuted = reader.ReadElementContentAsBoolean();
break;
case "IsModeratorMuted":
isModeratorMuted = reader.ReadElementContentAsBoolean();
break;
case "IsSpeaking":
isSpeaking = reader.ReadElementContentAsBoolean();
break;
case "Volume":
volume = reader.ReadElementContentAsInt();
break;
case "Energy":
energy = reader.ReadElementContentAsFloat();
break;
case "MicEnergy":
energy = reader.ReadElementContentAsFloat();
break;
case "ChannelURI":
uriString = reader.ReadElementContentAsString();
break;
case "ChannelListResult":
_ChannelMap[nameString] = uriString;
break;
case "CaptureDevice":
reader.Read();
_CaptureDevices.Add(reader.ReadElementContentAsString());
break;
case "CurrentCaptureDevice":
reader.Read();
nameString = reader.ReadElementContentAsString();
break;
case "RenderDevice":
reader.Read();
_RenderDevices.Add(reader.ReadElementContentAsString());
break;
case "CurrentRenderDevice":
reader.Read();
nameString = reader.ReadElementContentAsString();
break;
}
}
break;
}
case XmlNodeType.EndElement:
if (reader.Depth == 0)
ProcessEvent();
break;
}
}
if (isEvent)
{
}
//Client.DebugLog("VOICE: " + line);
}
private void ProcessEvent()
{
if (isEvent)
{
switch (eventTypeString)
{
case "LoginStateChangeEvent":
if (OnLoginStateChange != null) OnLoginStateChange(cookie, accountHandle, statusCode, statusString, state);
break;
case "SessionNewEvent":
if (OnNewSession != null) OnNewSession(cookie, accountHandle, eventSessionHandle, state, nameString, uriString);
break;
case "SessionStateChangeEvent":
if (OnSessionStateChange != null) OnSessionStateChange(cookie, uriString, statusCode, statusString, eventSessionHandle, state, isChannel, nameString);
break;
case "ParticipantStateChangeEvent":
if (OnParticipantStateChange != null) OnParticipantStateChange(cookie, uriString, statusCode, statusString, state, nameString, displayNameString, participantType);
break;
case "ParticipantPropertiesEvent":
if (OnParticipantProperties != null) OnParticipantProperties(cookie, uriString, statusCode, statusString, isLocallyMuted, isModeratorMuted, isSpeaking, volume, energy);
break;
case "AuxAudioPropertiesEvent":
if (OnAuxAudioProperties != null) OnAuxAudioProperties(cookie, energy);
break;
}
}
else
{
switch (actionString)
{
case "Connector.Create.1":
if (OnConnectorCreated != null) OnConnectorCreated(cookie, statusCode, statusString, connectorHandle);
break;
case "Account.Login.1":
if (OnLogin != null) OnLogin(cookie, statusCode, statusString, accountHandle);
break;
case "Session.Create.1":
if (OnSessionCreated != null) OnSessionCreated(cookie, statusCode, statusString, sessionHandle);
break;
case "Session.Connect.1":
if (OnSessionConnected != null) OnSessionConnected(cookie, statusCode, statusString);
break;
case "Session.Terminate.1":
if (OnSessionTerminated != null) OnSessionTerminated(cookie, statusCode, statusString);
break;
case "Account.Logout.1":
if (OnAccountLogout != null) OnAccountLogout(cookie, statusCode, statusString);
break;
case "Connector.InitiateShutdown.1":
if (OnConnectorInitiateShutdown != null) OnConnectorInitiateShutdown(cookie, statusCode, statusString);
break;
case "Account.ChannelGetList.1":
if (OnAccountChannelGetList != null) OnAccountChannelGetList(cookie, statusCode, statusString);
break;
case "Aux.GetCaptureDevices.1":
if (OnCaptureDevices != null) OnCaptureDevices(cookie, statusCode, statusString, nameString);
break;
case "Aux.GetRenderDevices.1":
if (OnRenderDevices != null) OnRenderDevices(cookie, statusCode, statusString, nameString);
break;
}
}
}
#endregion Callbacks
}
}
@@ -0,0 +1,157 @@
/*
* Copyright (c) 2006-2014, openmetaverse.org
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the openmetaverse.org nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Threading;
using OpenMetaverse;
namespace OpenMetaverse.Utilities
{
public partial class VoiceManager
{
/// <summary>Amount of time to wait for the voice daemon to respond.
/// The value needs to stay relatively high because some of the calls
/// require the voice daemon to make remote queries before replying</summary>
public int BlockingTimeout = 30 * 1000;
protected Dictionary<int, AutoResetEvent> Events = new Dictionary<int, AutoResetEvent>();
public List<string> CaptureDevices()
{
AutoResetEvent evt = new AutoResetEvent(false);
Events[_CommandCookie] = evt;
if (RequestCaptureDevices() == -1)
{
Events.Remove(_CommandCookie);
return new List<string>();
}
if (evt.WaitOne(BlockingTimeout, false))
return CurrentCaptureDevices();
else
return new List<string>();
}
public List<string> RenderDevices()
{
AutoResetEvent evt = new AutoResetEvent(false);
Events[_CommandCookie] = evt;
if (RequestRenderDevices() == -1)
{
Events.Remove(_CommandCookie);
return new List<string>();
}
if (evt.WaitOne(BlockingTimeout, false))
return CurrentRenderDevices();
else
return new List<string>();
}
public string CreateConnector(out int status)
{
status = 0;
AutoResetEvent evt = new AutoResetEvent(false);
Events[_CommandCookie] = evt;
if (RequestCreateConnector() == -1)
{
Events.Remove(_CommandCookie);
return String.Empty;
}
bool success = evt.WaitOne(BlockingTimeout, false);
status = statusCode;
if (success && statusCode == 0)
return connectorHandle;
else
return String.Empty;
}
public string Login(string accountName, string password, string connectorHandle, out int status)
{
status = 0;
AutoResetEvent evt = new AutoResetEvent(false);
Events[_CommandCookie] = evt;
if (RequestLogin(accountName, password, connectorHandle) == -1)
{
Events.Remove(_CommandCookie);
return String.Empty;
}
bool success = evt.WaitOne(BlockingTimeout, false);
status = statusCode;
if (success && statusCode == 0)
return accountHandle;
else
return String.Empty;
}
protected void RegisterCallbacks()
{
OnCaptureDevices += new DevicesCallback(VoiceManager_OnCaptureDevices);
OnRenderDevices += new DevicesCallback(VoiceManager_OnRenderDevices);
OnConnectorCreated += new ConnectorCreatedCallback(VoiceManager_OnConnectorCreated);
OnLogin += new LoginCallback(VoiceManager_OnLogin);
}
#region Callbacks
private void VoiceManager_OnCaptureDevices(int cookie, int statusCode, string statusString, string currentDevice)
{
if (Events.ContainsKey(cookie))
Events[cookie].Set();
}
private void VoiceManager_OnRenderDevices(int cookie, int statusCode, string statusString, string currentDevice)
{
if (Events.ContainsKey(cookie))
Events[cookie].Set();
}
private void VoiceManager_OnConnectorCreated(int cookie, int statusCode, string statusString, string connectorHandle)
{
if (Events.ContainsKey(cookie))
Events[cookie].Set();
}
private void VoiceManager_OnLogin(int cookie, int statusCode, string statusString, string accountHandle)
{
if (Events.ContainsKey(cookie))
Events[cookie].Set();
}
#endregion Callbacks
}
}