mirror of
https://github.com/TechplexEngineer/plexview.git
synced 2026-07-29 19:00:08 +00:00
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:
@@ -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")]
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user